[MERGE] merged trunk.

bzr revid: vmt@openerp.com-20130605120443-wgt24723597pak4b
This commit is contained in:
Vo Minh Thu 2013-06-05 14:04:43 +02:00
commit 1ed9049041
376 changed files with 633348 additions and 450569 deletions

View File

@ -17,3 +17,5 @@ include/
lib/
share/
doc/_build/*
win32/*.bat
win32/meta.py

View File

@ -7,7 +7,7 @@ graft win32
include README
include LICENSE
include MANIFEST.in
include gunicorn.conf.py
include openerp-wsgi.py
include openerp-server
include setup*
global-exclude *pyc *~ # Exclude possible garbage from previous graft.

View File

@ -1,19 +0,0 @@
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import sys
if __name__ == "__main__":
print '-' * 70
print "DEPRECATED: you are starting the OpenERP server with its old path,"
print "please use the new executable (available in the parent directory)."
print '-' * 70
# Change to the parent directory ...
os.chdir(os.path.normpath(os.path.dirname(__file__)))
os.chdir('..')
# ... and execute the new executable.
os.execv('openerp-server', sys.argv)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

10
debian/control vendored
View File

@ -19,10 +19,13 @@ Depends:
python-docutils,
python-feedparser,
python-gdata,
python-imaging,
python-jinja2,
python-ldap,
python-libxslt1,
python-lxml,
python-mako,
python-mock,
python-openid,
python-psutil,
python-psycopg2,
@ -33,6 +36,7 @@ Depends:
python-reportlab,
python-simplejson,
python-tz,
python-unittest2,
python-vatnumber,
python-vobject,
python-webdav,
@ -43,12 +47,12 @@ Depends:
Conflicts: tinyerp-server, openerp-server, openerp-web
Replaces: tinyerp-server, openerp-server, openerp-web
Recommends:
graphviz, ghostscript, postgresql, python-imaging, python-matplotlib
graphviz, ghostscript, postgresql, python-matplotlib, poppler-utils
Description: OpenERP Enterprise Resource Management
OpenERP, previously known as TinyERP, is a complete ERP and CRM. The main
features are accounting (analytic and financial), stock management, sales and
purchases management, tasks automation, marketing campaigns, help desk, POS,
etc. Technical features include a distributed server, flexible workflows, an
object database, a dynamic GUI, customizable reports, and NET-RPC and XML-RPC
interfaces.
object database, a dynamic GUI, customizable reports, and an XML-RPC
interface.

69
debian/openerp.init vendored
View File

@ -17,55 +17,46 @@ DAEMON=/usr/bin/openerp-server
NAME=openerp-server
DESC=openerp-server
CONFIG=/etc/openerp/openerp-server.conf
LOGFILE=/var/log/openerp-server.log
LOGFILE=/var/log/openerp/openerp-server.log
USER=openerp
test -x ${DAEMON} || exit 0
set -e
do_start () {
echo -n "Starting ${DESC}: "
start-stop-daemon --start --quiet --pidfile /var/run/${NAME}.pid --chuid ${USER} --background --make-pidfile --exec ${DAEMON} -- --config=${CONFIG} --logfile=${LOGFILE}
echo "${NAME}."
}
do_stop () {
echo -n "Stopping ${DESC}: "
start-stop-daemon --stop --quiet --pidfile /var/run/${NAME}.pid --oknodo
echo "${NAME}."
}
case "${1}" in
start)
echo -n "Starting ${DESC}: "
start)
do_start
;;
start-stop-daemon --start --quiet --pidfile /var/run/${NAME}.pid \
--chuid ${USER} --background --make-pidfile \
--exec ${DAEMON} -- --config=${CONFIG} \
--logfile=${LOGFILE}
stop)
do_stop
;;
echo "${NAME}."
;;
restart|force-reload)
echo -n "Restarting ${DESC}: "
do_stop
sleep 1
do_start
;;
stop)
echo -n "Stopping ${DESC}: "
start-stop-daemon --stop --quiet --pidfile /var/run/${NAME}.pid \
--oknodo
echo "${NAME}."
;;
restart|force-reload)
echo -n "Restarting ${DESC}: "
start-stop-daemon --stop --quiet --pidfile /var/run/${NAME}.pid \
--oknodo
sleep 1
start-stop-daemon --start --quiet --pidfile /var/run/${NAME}.pid \
--chuid ${USER} --background --make-pidfile \
--exec ${DAEMON} -- --config=${CONFIG} \
--logfile=${LOGFILE}
echo "${NAME}."
;;
*)
N=/etc/init.d/${NAME}
echo "Usage: ${NAME} {start|stop|restart|force-reload}" >&2
exit 1
;;
*)
N=/etc/init.d/${NAME}
echo "Usage: ${NAME} {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0

View File

@ -12,9 +12,9 @@ case "${1}" in
chown openerp:openerp /etc/openerp/openerp-server.conf
chmod 0640 /etc/openerp/openerp-server.conf
# Creating log file
touch /var/log/openerp-server.log
chown openerp:openerp /var/log/openerp-server.log
chmod 0640 /var/log/openerp-server.log
mkdir -p /var/log/openerp/
chown openerp:openerp /var/log/openerp
chmod 0750 /var/log/openerp
# Creating local storage directory
mkdir -p /var/lib/openerp/filestore
chown openerp:openerp -R /var/lib/openerp

View File

@ -6,10 +6,11 @@ case "${1}" in
remove)
deluser --quiet --system "openerp" || true
delgroup --quiet --system --only-if-empty "openerp" || true
find /var/lib/openerp -path '/var/lib/openerp/*' ! -path '/var/lib/openerp/filestore*' -delete
;;
purge)
rm -rf /var/lib/openerp-server
rm -rf /var/lib/openerp
;;
upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)

View File

@ -10,13 +10,25 @@ Installation from sources
.. _getting_started_installation_source-link:
Source code is hosted on Launchpad_. In order to get the sources, you will need Bazaar_ to pull the source from Launchpad. Bazaar is a version control system that helps you track project history over time and collaborate efficiently. You may have to create an account on Launchpad to be able to collaborate on OpenERP development. Please refer to the Launchpad and Bazaar documentation to install and setup your development environment.
Source code is hosted on Launchpad_. In order to get the sources, you
will need Bazaar_ to pull the source from Launchpad. Bazaar is a
version control system that helps you track project history over time
and collaborate efficiently. You may have to create an account on
Launchpad to be able to collaborate on OpenERP development. Please
refer to the Launchpad and Bazaar documentation to install and setup
your development environment.
The running example of this section is based on an Ubuntu environment. You may have to adapt the steps according to your system. Once your working environment is ready, prepare a working directory that will contain the sources. For a ``source`` base directory, type::
The running example of this section is based on an Ubuntu
environment. You may have to adapt the steps according to your
system. Once your working environment is ready, prepare a working
directory that will contain the sources. For a ``source`` base
directory, type::
mkdir source;cd source
OpenERP provides a setup script that automatizes the tasks of creating a shared repository and getting the source code. Get the setup script of OpenERP by typing::
OpenERP provides a setup script that automatizes the tasks of creating
a shared repository and getting the source code. Get the setup script
of OpenERP by typing::
bzr cat -d lp:~openerp-dev/openerp-tools/trunk setup.sh | sh
@ -29,27 +41,30 @@ If you want some help about the available options, please type::
make help
Next step is to initialize the shared repository and download the sources. Get the current trunk version of OpenERP by typing::
Next step is to initialize the shared repository and download the
sources. Get the current trunk version of OpenERP by typing::
make init-trunk
This will create the following structure inside your ``source`` directory, and fetch the latest source code from ``trunk``::
This will create the following structure inside your ``source``
directory, and fetch the latest source code from ``trunk``::
drwxrwxr-x 3 openerp openerp 4096 2012-04-17 11:10 addons
drwxrwxr-x 3 openerp openerp 4096 2012-04-17 11:10 misc
drwxrwxr-x 3 openerp openerp 4096 2012-04-17 11:10 server
drwxrwxr-x 3 openerp openerp 4096 2012-04-17 11:10 web
Some dependencies are necessary to use OpenERP. Depending on your environment, you might have to install the following packages::
Some dependencies are necessary to use OpenERP. Depending on your
environment, you might have to install the following packages::
sudo apt-get install graphviz ghostscript postgresql-client
sudo apt-get install python-dateutil python-feedparser python-gdata
python-ldap python-libxslt1 python-lxml python-mako, python-openid
python-psycopg2 python-pybabel python-pychart python-pydot
python-pyparsing python-reportlab python-simplejson python-tz
python-vatnumber python-vobject python-webdav python-werkzeug python-xlwt
python-yaml python-imaging python-matplotlib
sudo apt-get install graphviz ghostscript postgresql-client \
python-dateutil python-feedparser python-gdata \
python-ldap python-libxslt1 python-lxml python-mako \
python-openid python-psycopg2 python-pybabel python-pychart \
python-pydot python-pyparsing python-reportlab python-simplejson \
python-tz python-vatnumber python-vobject python-webdav \
python-werkzeug python-xlwt python-yaml python-imaging \
python-matplotlib
Next step is to initialize the database. This will create a new openerp role::
@ -59,7 +74,8 @@ Finally, launch the OpenERP server::
make server
Testing your installation can be done on http://localhost:8069/ . You should see the OpenERP main login page.
Testing your installation can be done on http://localhost:8069/. You
should see the OpenERP main login page.
.. _Launchpad: https://launchpad.net/
.. _Bazaar: http://bazaar.canonical.com/en/
@ -67,12 +83,12 @@ Testing your installation can be done on http://localhost:8069/ . You should see
Command line options
====================
.. program:: openerp-server
Using the command ::
./openerp-server --help
gives you the available command line options. For OpenERP server at revision 4133, an output example is given in the `Command line options example`_. Here are a few interesting command line options.
General Options
+++++++++++++++
@ -87,9 +103,6 @@ General Options
--logfile=LOGFILE file where the server log will be stored
-n INTERFACE, --interface=INTERFACE specify the TCP IP address
-p PORT, --port=PORT specify the TCP port
--net_interface=NETINTERFACE specify the TCP IP address for netrpc
--net_port=NETPORT specify the TCP port for netrpc
--no-netrpc disable netrpc
--no-xmlrpc disable xmlrpc
-i INIT, --init=INIT init a module (use "all" for all modules)
--without-demo=WITHOUT_DEMO load demo data for a module (use "all" for all modules)
@ -117,7 +130,8 @@ Database related options
Internationalization options
++++++++++++++++++++++++++++
Use these options to translate OpenERP to another language.See i18n section of the user manual. Option '-l' is mandatory.::
Use these options to translate OpenERP to another language.See i18n
section of the user manual. Option '-l' is mandatory.::
-l LANGUAGE, --language=LANGUAGE
specify the language of the translation file. Use it
@ -134,8 +148,9 @@ Use these options to translate OpenERP to another language.See i18n section of t
Options from previous versions
++++++++++++++++++++++++++++++
Some options were removed in OpenERP version 6. For example, ``price_accuracy`` is now
configured through the :ref:`decimal_accuracy` screen.
Some options were removed in OpenERP version 6. For example,
``price_accuracy`` is now configured through the
:ref:`decimal_accuracy` screen.
Configuration
==============
@ -147,7 +162,12 @@ Two configuration files are available:
* one for the client: ``~/.openerprc``
* one for the server: ``~/.openerp_serverrc``
If they are not found, the server and the client will start with a default configuration. Those files follow the convention used by python's ConfigParser module. Please note that lines beginning with "#" or ";" are comments. The client configuration file is automatically generated upon the first start. The sezrver configuration file can automatically be created using the command ::
If they are not found, the server and the client will start with a
default configuration. Those files follow the convention used by
python's ConfigParser module. Please note that lines beginning with
"#" or ";" are comments. The client configuration file is
automatically generated upon the first start. The sezrver
configuration file can automatically be created using the command ::
./openerp-server -s or ./openerp-server --save
@ -155,15 +175,31 @@ You can specify alternate configuration files with ::
-c CONFIG, --config=CONFIG specify alternate config file
Configure addons locations
++++++++++++++++++++++++++
By default, the only directory of addons known by the server is
server/bin/addons. It is possible to add new addons by
- copying them in server/bin/addons, or creating a symbolic link to
each of them in this directory, or
- specifying another directory containing addons to the server. The
later can be accomplished either by running the server with the
``--addons-path=`` option, or by configuring this option in the
openerp_serverrc file, automatically generated under Linux in your
home directory by the server when executed with the ``--save``
option. You can provide several addons to the ``addons_path`` =
option, separating them using commas.
Start-up script
===============
.. versionadded:: 6.1
To run the OpenERP server, the conventional approach is to use the
`openerp-server` script. It loads the :ref:`openerp library`, sets a few
configuration variables corresponding to command-line arguments, and starts to
listen to incoming connections from clients.
`openerp-server` script. It loads the :ref:`openerp library`, sets a
few configuration variables corresponding to command-line arguments,
and starts to listen to incoming connections from clients.
Depending on your deployment needs, you can write such a start-up script very
easily. We also recommend you take a look at an alternative tool called
@ -173,283 +209,3 @@ Yet another alternative is to use a WSGI-compatible HTTP server and let it call
into one of the WSGI entry points of the server.
Appendix
========
Command line options example
++++++++++++++++++++++++++++
Usage: openerp-server [options]
**Options**::
--version show program's version number and exit
-h, --help show this help message and exit
**Common options**::
-c CONFIG, --config=CONFIG
specify alternate config file
-s, --save save configuration to ~/.openerp_serverrc
-i INIT, --init=INIT
install one or more modules (comma-separated list, use
"all" for all modules), requires -d
-u UPDATE, --update=UPDATE
update one or more modules (comma-separated list, use
"all" for all modules). Requires -d.
--without-demo=WITHOUT_DEMO
disable loading demo data for modules to be installed
(comma-separated, use "all" for all modules). Requires
-d and -i. Default is none
-P IMPORT_PARTIAL, --import-partial=IMPORT_PARTIAL
Use this for big data importation, if it crashes you
will be able to continue at the current state. Provide
a filename to store intermediate importation states.
--pidfile=PIDFILE file where the server pid will be stored
--addons-path=ADDONS_PATH
specify additional addons paths (separated by commas).
--load=SERVER_WIDE_MODULES
Comma-separated list of server-wide modules
default=web
**XML-RPC Configuration**::
--xmlrpc-interface=XMLRPC_INTERFACE
Specify the TCP IP address for the XML-RPC protocol.
The empty string binds to all interfaces.
--xmlrpc-port=XMLRPC_PORT
specify the TCP port for the XML-RPC protocol
--no-xmlrpc disable the XML-RPC protocol
--proxy-mode Enable correct behavior when behind a reverse proxy
**XML-RPC Secure Configuration**::
--xmlrpcs-interface=XMLRPCS_INTERFACE
Specify the TCP IP address for the XML-RPC Secure
protocol. The empty string binds to all interfaces.
--xmlrpcs-port=XMLRPCS_PORT
specify the TCP port for the XML-RPC Secure protocol
--no-xmlrpcs disable the XML-RPC Secure protocol
--cert-file=SECURE_CERT_FILE
specify the certificate file for the SSL connection
--pkey-file=SECURE_PKEY_FILE
specify the private key file for the SSL connection
**NET-RPC Configuration**::
--netrpc-interface=NETRPC_INTERFACE
specify the TCP IP address for the NETRPC protocol
--netrpc-port=NETRPC_PORT
specify the TCP port for the NETRPC protocol
--no-netrpc disable the NETRPC protocol
**Web interface Configuration**::
--db-filter=REGEXP Filter listed database
**Static HTTP service**::
--static-http-enable
enable static HTTP service for serving plain HTML
files
--static-http-document-root=STATIC_HTTP_DOCUMENT_ROOT
specify the directory containing your static HTML
files (e.g '/var/www/')
--static-http-url-prefix=STATIC_HTTP_URL_PREFIX
specify the URL root prefix where you want web
browsers to access your static HTML files (e.g '/')
**Testing Configuration**::
--test-file=TEST_FILE
Launch a YML test file.
--test-report-directory=TEST_REPORT_DIRECTORY
If set, will save sample of all reports in this
directory.
--test-enable Enable YAML and unit tests.
--test-commit Commit database changes performed by YAML or XML
tests.
**Logging Configuration**::
--logfile=LOGFILE file where the server log will be stored
--no-logrotate do not rotate the logfile
--syslog Send the log to the syslog server
--log-handler=PREFIX:LEVEL
setup a handler at LEVEL for a given PREFIX. An empty
PREFIX indicates the root logger. This option can be
repeated. Example: "openerp.orm:DEBUG" or
"werkzeug:CRITICAL" (default: ":INFO")
--log-request shortcut for --log-
handler=openerp.netsvc.rpc.request:DEBUG
--log-response shortcut for --log-
handler=openerp.netsvc.rpc.response:DEBUG
--log-web shortcut for --log-
handler=openerp.addons.web.common.http:DEBUG
--log-sql shortcut for --log-handler=openerp.sql_db:DEBUG
--log-level=LOG_LEVEL
specify the level of the logging. Accepted values:
['info', 'debug_rpc', 'warn', 'test', 'critical',
'debug_sql', 'error', 'debug', 'debug_rpc_answer',
'notset'] (deprecated option).
**SMTP Configuration**::
--email-from=EMAIL_FROM
specify the SMTP email address for sending email
--smtp=SMTP_SERVER specify the SMTP server for sending email
--smtp-port=SMTP_PORT
specify the SMTP port
--smtp-ssl specify the SMTP server support SSL or not
--smtp-user=SMTP_USER
specify the SMTP username for sending email
--smtp-password=SMTP_PASSWORD
specify the SMTP password for sending email
**Database related options**::
-d DB_NAME, --database=DB_NAME
specify the database name
-r DB_USER, --db_user=DB_USER
specify the database user name
-w DB_PASSWORD, --db_password=DB_PASSWORD
specify the database password
--pg_path=PG_PATH specify the pg executable path
--db_host=DB_HOST specify the database host
--db_port=DB_PORT specify the database port
--db_maxconn=DB_MAXCONN
specify the the maximum number of physical connections
to posgresql
--db-template=DB_TEMPLATE
specify a custom database template to create a new
database
**Internationalisation options**::
Use these options to translate OpenERP to another language.See i18n
section of the user manual. Option '-d' is mandatory.Option '-l' is
mandatory in case of importation
--load-language=LOAD_LANGUAGE
specifies the languages for the translations you want
to be loaded
-l LANGUAGE, --language=LANGUAGE
specify the language of the translation file. Use it
with --i18n-export or --i18n-import
--i18n-export=TRANSLATE_OUT
export all sentences to be translated to a CSV file, a
PO file or a TGZ archive and exit
--i18n-import=TRANSLATE_IN
import a CSV or a PO file with translations and exit.
The '-l' option is required.
--i18n-overwrite overwrites existing translation terms on updating a
module or importing a CSV or a PO file.
--modules=TRANSLATE_MODULES
specify modules to export. Use in combination with
--i18n-export
**Security-related options**::
--no-database-list disable the ability to return the list of databases
**Advanced options**::
--cache-timeout=CACHE_TIMEOUT
set the timeout for the cache system
--debug enable debug mode
--stop-after-init stop the server after its initialization
-t TIMEZONE, --timezone=TIMEZONE
specify reference timezone for the server (e.g.
Europe/Brussels
--osv-memory-count-limit=OSV_MEMORY_COUNT_LIMIT
Force a limit on the maximum number of records kept in
the virtual osv_memory tables. The default is False,
which means no count-based limit.
--osv-memory-age-limit=OSV_MEMORY_AGE_LIMIT
Force a limit on the maximum age of records kept in
the virtual osv_memory tables. This is a decimal value
expressed in hours, and the default is 1 hour.
--max-cron-threads=MAX_CRON_THREADS
Maximum number of threads processing concurrently cron
jobs.
--virtual-memory-limit=VIRTUAL_MEMORY_LIMIT
Maximum allowed virtual memory per Gunicorn process.
When the limit is reached, any memory allocation will
fail.
--virtual-memory-reset=VIRTUAL_MEMORY_RESET
Maximum allowed virtual memory per Gunicorn process.
When the limit is reached, the worker will be reset
after the current request.
--cpu-time-limit=CPU_TIME_LIMIT
Maximum allowed CPU time per Gunicorn process. When
the limit is reached, an exception is raised.
--unaccent Use the unaccent function provided by the database
when available.
Server configuration file
+++++++++++++++++++++++++
::
[options]
addons_path = /home/openerp/workspace/openerp-dev/addons/trunk,/home/openerp/workspace/openerp-dev/web/trunk/addons
admin_passwd = admin
cache_timeout = 100000
cpu_time_limit = 60
csv_internal_sep = ,
db_host = False
db_maxconn = 64
db_name = False
db_password = False
db_port = False
db_template = template0
db_user = openerp
dbfilter = .*
debug_mode = False
demo = {}
email_from = False
import_partial =
list_db = True
log_handler = [':INFO']
log_level = info
logfile = False
login_message = False
logrotate = True
max_cron_threads = 4
netrpc = True
netrpc_interface =
netrpc_port = 8070
osv_memory_age_limit = 1.0
osv_memory_count_limit = False
pg_path = None
pidfile = False
proxy_mode = False
reportgz = False
secure_cert_file = server.cert
secure_pkey_file = server.pkey
server_wide_modules = None
smtp_password = False
smtp_port = 25
smtp_server = localhost
smtp_ssl = False
smtp_user = False
static_http_document_root = None
static_http_enable = False
static_http_url_prefix = None
syslog = False
test_commit = False
test_enable = False
test_file = False
test_report_directory = False
timezone = False
translate_modules = ['all']
unaccent = False
virtual_memory_limit = 805306368
virtual_memory_reset = 671088640
without_demo = False
xmlrpc = True
xmlrpc_interface =
xmlrpc_port = 8069
xmlrpcs = True
xmlrpcs_interface =
xmlrpcs_port = 8071

View File

@ -1,6 +1,6 @@
========================================
============
Architecture
========================================
============
OpenERP as a multitenant three-tiers architecture
=================================================
@ -33,16 +33,11 @@ three main components:
Another layer allows communications between the server and a web browser,
the Web layer. Having more than one server is possible, for example in
conjunction with a load balancing mechanism.
- the client, which allow users to access OpenERP. Two clients exist, a
desktop GTK client and a browser-based client
- the client running in the a web browser as javascript application.
- the GTK client access directly to the OpenERP Server
- users can also use standard web browsers to access OpenERP. In that
case, an OpenERP application is loaded. It handles communications between
the browser and the Web layer of the server.
The database server and the OpenERP server can be installed on the same computer,
or distributed onto separate computer servers, for example for performance considerations.
The database server and the OpenERP server can be installed on the same
computer, or distributed onto separate computer servers, for example for
performance considerations.
.. _`Figure 1`:
.. figure:: _static/02_openerp_architecture.png
@ -116,8 +111,9 @@ The services granted by the ORM are among other :
The web layer offers an interface to communicate with standard browsers.
In the 6.1 version of OpenERP, the web-client has been rewritten and integrated
into the OpenERP server tier. This layer relies on CherryPy for the routing
layer of communications, especially for session and cookies management.
into the OpenERP server tier. This web layer is a WSGI-compatible application
based on werkzeug. It handles regular http queries to server static file or
dynamic content and JSON-RPC queries for the RPC made from the browser.
**Modules**
@ -137,20 +133,8 @@ and display the result (e.g. a list of customers) in different ways
(as forms, lists, calendars, ...). Upon user actions, it sends queries
to modify data to the server.
Two clients can be used for user access to OpenERP, a GTK client and a
browser-based client. The GTK client communicates directly with the server.
Using the GTK client requires the client to be installed on the workstation
of each user.
The browser-based client holds an OpenERP application that handles communications
between the browser and the Web layer of the server. The static code of the web
application is minimal. It consists of a minimal flow of HTML that is in charge
of loading the application code in Javascript. This client-side OpenERP application
sends user requests to the server, and gets data back. Data management is
done dynamically in this client. Using this client is therefore easy for
users, but also for administrators because it does not require any software
installation on the user machine.
The default client of OpenERP is an JavaScript application running in the
browser that communicates with the server using JSON-RPC.
MVC architecture in OpenERP
===========================
@ -194,37 +178,75 @@ OpenERP follows the MVC semantic with
- view : views are defined in XML files in OpenERP.
- controller : The objects of OpenERP.
Network communications and WSGI
===============================
Network communications
======================
OpenERP is an HTTP web server and may also be deployed as an WSGI-compliant
application.
GTK clients communicate with the OpenERP server using XML-RPC protocol by
default. However, using a secured version XML-RPCS is possible when configurating
your OpenERP instance. In previous versions of OpenERP, a custom protocol
called NET-RPC was used. It was a binary version of the XML-RPC protocol,
allowing faster communications. However, this protocol will no longer be
used in OpenERP. The use of JSON-RPC is also planned for the 6.1 version
of OpenERP.
Web-based clients communicate using HTTP protocol. As for XML-RPC, it is
possible to configure OpenERP to use secured HTTPS connections.
Services and WSGI
=================
Clients may communicate with OpenERP using sessionless XML-RPC, the recommended
way to interoperate with OpenERP. Web-based clients communicates using the
session aware JSON-RPC.
Everything in OpenERP, and objects methods in particular, are exposed via
the network and a security layer. Access to the data model is in fact a service
and it is possible to expose new services. For instance, a WebDAV service and
a FTP service are available.
While not mandatory, the services can make use of the `WSGI
<http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface>`_ stack. WSGI is
a standard solution in the Python ecosystem to write HTTP servers, applications,
and middleware which can be used in a mix-and-match fashion. By using WSGI,
it is possible to run OpenERP in any WSGI compliant server. It is also
possible to use OpenERP to host a WSGI application.
Services can make use of the `WSGI
<http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface>`_ stack. WSGI is a
standard solution in the Python ecosystem to write HTTP servers, applications,
and middleware which can be used in a mix-and-match fashion. By using WSGI, it
is possible to run OpenERP in any WSGI compliant server. It is also possible to
use OpenERP to host a WSGI application.
A striking example of this possibility is the OpenERP Web layer that is
the server-side counter part to the web clients. It provides the requested
data to the browser and manages web sessions. It is a WSGI-compliant application.
As such, it can be run as a stand-alone HTTP server or embedded inside OpenERP.
The HTTP namespaces /openerp/ /object/ /common/ are reserved for the XML-RPC
layer, every module restrict it's HTTP namespace to /<name_of_the_module>/
Process model
=============
In the past, the OpenERP server was using threads to handle HTTP requests
concurrently or to process cron jobs. Using threads is still the default
behavior when running the ``openerp-server`` script but not the recommended
one: it is in fact recommended to use the ``--workers`` option.
By using the ``--workers`` option, the OpenERP server will spawn a fixed number
of processes instead of spawning a new thread for each incoming request.
This has a number of advantages:
- Processes do not suffer from CPython's Global Interpreter Lock.
- Processes can be gracefully recycled while requests are still handled by the
server.
- Resources such as CPU time and memory made available to a process can be
monitored on a per-process basis.
When using the ``--workers`` options, two types of processes may be spawned:
web process, and cron process.
.. versionadded:: 7.1
.. _longpolling-worker:
When using the ``--workers`` options, three types of processes may be spawned:
web process, and cron process, just as previsouly, but also an evented (using
gevent) web process is started. It is used for long-polling as needed by the
upcoming Instant Messaging feature. As for now, that process is listening on a
different port than the main web processes. A reverse proxy (e.g. Nginx) to
listen on a unique port, mapping all requests to the normal port, but mapping
the ``/longpolling`` route to the evented process is necessary (the web
interface cannot issue requests to different ports).
(It is possible to make the threaded server evented by passing the ``--gevent``
flag.)
The goal is to drop support for the threaded model, and also make all web
processes evented; there would be no more distinction between "normal" and
"longpolling" processes. For this to happen, further testing is needed.

View File

@ -1,3 +1,5 @@
.. _module-dev:
=======
Modules
=======
@ -11,3 +13,4 @@ Modules
03_module_dev_04
03_module_dev_05
03_module_dev_06
report-declaration

View File

@ -1,18 +1,19 @@
.. _module-dev-structure:
Module structure
================
A module can contain the following elements:
- **Business object** : declared as Python classes extending the OpenObject c
lass osv.Model, the persistence of these resource is completly managed
by OpenObject,
- **Business object** : declared as Python classes extending the class
osv.Model, the persistence of these resource is completly managed by
OpenERP's ORM.
- **Data** : XML/CSV files with meta-data (views and workflows declaration),
configuration data (modules parametrization) and demo data (optional but
recommended for testing),
- **Wizards** : stateful interactive forms used to assist users, often available
as contextual actions on resources,
- **Reports** : RML (XML format). MAKO or OpenOffice report templates, to be
merged with any kind of business data, and generate HTML, ODT or PDF reports.
- **Reports** : RML (XML format). HTML/MAKO or OpenOffice report templates, to
be merged with any kind of business data, and generate HTML, ODT or PDF
reports.
.. figure:: _static/03_module_gen_view.png
:width: 75%
@ -23,120 +24,91 @@ A module can contain the following elements:
Each module is contained in its own directory within either the server/bin/addons
directory or another directory of addons, configured in server installation.
To create a new module, the following steps are required:
To create a new module for example the 'OpenAcademy' module, the following
steps are required:
- create a ``my_module`` subdirectory in the source/addons directory
- create the module description file ``__init__.py``
- create the module declaration file ``__openerp__.py``
- create a ``openacademy`` subdirectory in the source/addons directory
- create the module import file ``__init__.py``
- create the module manifield file ``__openerp__.py``
- create **Python** files containing **objects**
- create **.xml files** holding module data such as views, menu entries
or demo data
- optionally create **reports**, **wizards** or **workflows**
- optionally create **reports** or **workflows**
Description file __init__.py
++++++++++++++++++++++++++++
Python import file __init__.py
++++++++++++++++++++++++++++++
The ``__init__.py`` file is the Python module descriptor, because an OpenERP
module is also a regular Python module. Like any Python module, it is executed
at program start. It needs to import the Python files that need to be loaded.
The ``__init__.py`` file is the Python import file, because an OpenERP module
is also a regular Python module. The file should import all the other python
file or submodules.
It contains the importation instruction applied to all Python files of the
module, without the .py extension. For example, if a module contains a single
python file named ``mymodule.py``, the file should look like:
For example, if a module contains a single python file named ``openacademy.py``,
the file should look like:
import module
import openacademy
Declaration file __openerp__.py
Manifest file __openerp__.py
+++++++++++++++++++++++++++++++
In the created module directory, you must add a **__openerp__.py** file.
This file, which must be in Python format, is responsible to
This file, which must be a Python dict literal, is responsible to
1. determine the *XML files that will be parsed* during the initialization
of the server, and also to
2. determine the *dependencies* of the created module.
3. declare additional meta data
This file must contain a Python dictionary with the following values:
::
name The (Plain English) name of the module.
name The name of the module in English.
version The version of the module.
summary Short description or keywords
description The module description (text).
category The categrory of the module
author The author of the module.
website The website of the module.
license The license of the module (default:GPL-2).
depends List of modules on which this module depends. The base
module must almost always be in the dependencies because
some necessary data for the views, reports, ... are in
the base module.
init_xml List of .xml files to load when the server is launched
with the "--init=module" argument. Filepaths must be
relative to the directory where the module is. OpenERP
XML file format is detailed in this section.
update_xml List of .xml files to load when the server is launched with
the "--update=module" launched. Filepaths must be relative
to the directory where the module is. Files in **update_xml**
concern: views, reports and wizards.
website URL of the website of the module.
license The license of the module (default: AGPL-3).
depends List of modules on which this module depends beside base.
data List of .xml files to load when the module is installed or updated.
demo List of additional .xml files to load when the module is
installed or updated and demo flag is active.
installable True or False. Determines whether the module is installable
or not.
auto_install True or False (default: False). If set to ``True``, the
module is a link module. It will be installed as soon
as all its dependencies are installed.
For the ``my_module`` module, here is an example of ``__openerp__.py``
For the ``openacademy`` module, here is an example of ``__openerp__.py``
declaration file:
.. code-block:: python
{
'name' : "My Module",
'name' : "OpenAcademy",
'version' : "1.0",
'author' : "OpenERP",
'author' : "OpenERP SA",
'category' : "Tools",
'depends' : ['base',],
'init_xml' : [],
'demo_xml' : [
'module_demo.xml'
],
'update_xml' : [
'module_view.xml',
'data/module_data.xml',
'depends' : ['mail'],
'data' : [
'openacademy_view.xml',
'openacademy_data.xml',
'report/module_report.xml',
'wizard/module_wizard.xml',
],
'demo' : [
'openacademy_demo.xml'
],
'installable': True,
'auto_install': False,
}
The files that must be placed in init_xml are the ones that relate to the
workflow definition, data to load at the installation of the software and
the data for the demonstrations.
XML Files
+++++++++
XML files located in the module directory are used to modify the structure of
the database. They are used for many purposes, among which we can cite :
* initialization and demonstration data declaration,
* views declaration,
* reports declaration,
* wizards declaration,
* workflows declaration.
General structure of OpenERP XML files is more detailed in the
:ref:`xml-serialization` section. Look here if you are interested in learning
more about *initialization* and *demonstration data declaration* XML files. The
following section are only related to XML specific to *actions, menu entries,
reports, wizards* and *workflows* declaration.
Objects
+++++++
All OpenERP resources are objects: menus, actions, reports, invoices, partners, ... OpenERP is based on an object relational mapping of a database to control the information. Object names are hierarchical, as in the following examples:
All OpenERP resources are objects: invoices, partners. Metadata are also object
too: menus, actions, reports... Object names are hierarchical, as in the
following examples:
* account.transfer : a money transfer
* account.invoice : an invoice
@ -144,39 +116,40 @@ All OpenERP resources are objects: menus, actions, reports, invoices, partners,
Generally, the first word is the name of the module: account, stock, sale.
Other advantages of an ORM;
* simpler relations : invoice.partner.address[0].city
* objects have properties and methods: invoice.pay(3400 EUR),
* inheritance, high level constraints, ...
It is easier to manipulate one object (example, a partner) than several tables (partner address, categories, events, ...)
.. figure:: images/pom_3_0_3.png
:scale: 50
:align: center
*The Physical Objects Model of [OpenERP version 3.0.3]*
PostgreSQL and ORM
------------------
Those object are declared in python be subclassing osv.Model
The ORM of OpenERP is constructed over PostgreSQL. It is thus possible to
query the object used by OpenERP using the object interface or by directly
using SQL statements.
query the object used by OpenERP using the object interface (ORM) or by
directly using SQL statements.
But it is dangerous to write or read directly in the PostgreSQL database, as
you will shortcut important steps like constraints checking or workflow
modification.
.. note::
.. .. figure:: images/pom_3_0_3.png
.. :scale: 50
.. :align: center
The Physical Database Model of OpenERP
.. *The Physical Objects Model of [OpenERP version 3.0.3]*
Pre-Installed Data
------------------
XML Files
+++++++++
XML files located in the module directory are used to initialize or update the
the database when the module is installed or updated. They are used for many
purposes, among which we can cite :
* initialization and demonstration data declaration,
* views declaration,
* reports declaration,
* workflows declaration.
General structure of OpenERP XML files is more detailed in the
:ref:`xml-serialization` section. Look here if you are interested in learning
more about *initialization* and *demonstration data declaration* XML files. The
following section are only related to XML specific to *actions, menu entries,
reports, wizards* and *workflows* declaration.
Data can be inserted or updated into the PostgreSQL tables corresponding to the
OpenERP objects using XML files. The general structure of an OpenERP XML file
@ -188,12 +161,8 @@ is as follows:
<openerp>
<data>
<record model="model.name_1" id="id_name_1">
<field name="field1">
"field1 content"
</field>
<field name="field2">
"field2 content"
</field>
<field name="field1"> "field1 content" </field>
<field name="field2"> "field2 content" </field>
(...)
</record>
<record model="model.name_2" id="id_name_2">
@ -203,7 +172,52 @@ is as follows:
</data>
</openerp>
Fields content are strings that must be encoded as *UTF-8* in XML files.
Record Tag
//////////
**Description**
The addition of new data is made with the record tag. This one takes a
mandatory attribute : model. Model is the object name where the insertion has
to be done. The tag record can also take an optional attribute: id. If this
attribute is given, a variable of this name can be used later on, in the same
file, to make reference to the newly created resource ID.
A record tag may contain field tags. They indicate the record's fields value.
If a field is not specified the default value will be used.
The Record Field tag
////////////////////
The attributes for the field tag are the following:
name : mandatory
the field name
eval : optional
python expression that indicating the value to add
ref
reference to an id defined in this file
model
model to be looked up in the search
search
a query
**Example**
.. code-block:: xml
<record model="ir.actions.report.xml" id="l0">
<field name="model">account.invoice</field>
<field name="name">Invoices List</field>
<field name="report_name">account.invoice.list</field>
<field name="report_xsl">account/report/invoice.xsl</field>
<field name="report_xml">account/report/invoice.xml</field>
</record>
Let's review an example taken from the OpenERP source (base_demo.xml in the base module):
@ -250,47 +264,6 @@ The field **company_id** is a many-to-one relation from the user object to the c
This is a classical example of the use of **search** in demo data: here we do not really care about which partner we want to use for the test, so we give an empty list. Notice the **model** attribute is currently mandatory.
Record Tag
//////////
**Description**
The addition of new data is made with the record tag. This one takes a mandatory attribute : model. Model is the object name where the insertion has to be done. The tag record can also take an optional attribute: id. If this attribute is given, a variable of this name can be used later on, in the same file, to make reference to the newly created resource ID.
A record tag may contain field tags. They indicate the record's fields value. If a field is not specified the default value will be used.
**Example**
.. code-block:: xml
<record model="ir.actions.report.xml" id="l0">
<field name="model">account.invoice</field>
<field name="name">Invoices List</field>
<field name="report_name">account.invoice.list</field>
<field name="report_xsl">account/report/invoice.xsl</field>
<field name="report_xml">account/report/invoice.xml</field>
</record>
Field tag
/////////
The attributes for the field tag are the following:
name : mandatory
the field name
eval : optional
python expression that indicating the value to add
ref
reference to an id defined in this file
model
model to be looked up in the search
search
a query
Function tag
////////////
@ -311,69 +284,9 @@ eval
<function model="ir.ui.menu" name="search" eval="[[('name','=','Operations')]]"/>
Getitem tag
///////////
Takes a subset of the evaluation of the last child node of the tag.
type : mandatory
int or list
index : mandatory
int or string (a key of a dictionary)
**Example**
Evaluates to the first element of the list of ids returned by the function node
.. code-block:: xml
<getitem index="0" type="list">
<function model="ir.ui.menu" name="search" eval="[[('name','=','Operations')]]"/>
</getitem>
i18n
""""
Improving Translations
//////////////////////
.. describe:: Translating in launchpad
Translations are managed by
the `Launchpad Web interface <https://translations.launchpad.net/openobject>`_. Here, you'll
find the list of translatable projects.
Please read the `FAQ <https://answers.launchpad.net/rosetta/+faqs>`_ before asking questions.
.. describe:: Translating your own module
.. versionchanged:: 5.0
Contrary to the 4.2.x version, the translations are now done by module. So,
instead of an unique ``i18n`` folder for the whole application, each module has
its own ``i18n`` folder. In addition, OpenERP can now deal with ``.po`` [#f_po]_
files as import/export format. The translation files of the installed languages
are automatically loaded when installing or updating a module. OpenERP can also
generate a .tgz archive containing well organised ``.po`` files for each selected
module.
.. [#f_po] http://www.gnu.org/software/autoconf/manual/gettext/PO-Files.html#PO-Files
Process
"""""""
Defining the process
////////////////////
Through the interface and module recorder.
Then, put the generated XML in your own module.
Views
"""""
Technical Specifications - Architecture - Views
///////////////////////////////////////////////
+++++
Views are a way to represent the objects on the client side. They indicate to the client how to lay out the data coming from the objects on the screen.
@ -400,9 +313,9 @@ When you open an invoice, here is the chain of operations followed by the client
* The client asks (with XML-RPC) to the server what views are defined for the invoice object and what are the data it must show.
* The client displays the form according to the view
.. figure:: images/arch_view_use.png
:scale: 50
:align: center
.. .. figure:: images/arch_view_use.png
.. :scale: 50
.. :align: center
To develop new objects
//////////////////////
@ -431,9 +344,9 @@ The workflows describe these interactions with graphs. One or several workflows
Below is an example workflow used for sale orders. It must generate invoices and shipments according to certain conditions.
.. figure:: images/arch_workflow_sale.png
:scale: 85
:align: center
.. .. figure:: images/arch_workflow_sale.png
.. :scale: 85
.. :align: center
In this graph, the nodes represent the actions to be done:
@ -454,21 +367,23 @@ The squared nodes represent other Workflows;
* the shipping
i18n
----
Appendix
+++++++++
.. versionchanged:: 5.0
Configure addons locations
--------------------------
Each module has its own ``i18n`` folder. In addition, OpenERP can now deal with
``.po`` [#f_po]_ files as import/export format. The translation files of the
installed languages are automatically loaded when installing or updating a
module.
Translations are managed by the `Launchpad Web interface
<https://translations.launchpad.net/openobject>`_. Here, you'll find the list
of translatable projects.
Please read the `FAQ <https://answers.launchpad.net/rosetta/+faqs>`_ before asking questions.
.. [#f_po] http://www.gnu.org/software/autoconf/manual/gettext/PO-Files.html#PO-Files
By default, the only directory of addons known by the server is server/bin/addons.
It is possible to add new addons by
- copying them in server/bin/addons, or creating a symbolic link to each
of them in this directory, or
- specifying another directory containing addons to the server. The later
can be accomplished either by running the server with the ``--addons-path=``
option, or by configuring this option in the openerp_serverrc file,
automatically generated under Linux in your home directory by the
server when executed with the ``--save`` option. You can provide several
addons to the ``addons_path`` = option, separating them using commas.

View File

@ -1,3 +1,5 @@
.. _module-dev-api:
Objects, Fields and Methods
===========================

View File

@ -1,18 +1,29 @@
.. _module-dev-views:
Views and Events
================
Introduction to Views
---------------------
As all data of the program is stored in objects, as explained in the Objects section, how are these objects exposed to the user ? We will try to answer this question in this section.
As all data of the program is stored in objects, as explained in the Objects
section, how are these objects exposed to the user ? We will try to answer this
question in this section.
First of all, let's note that every resource type uses its own interface. For example, the screen to modify a partner's data is not the same as the one to modify an invoice.
First of all, let's note that every resource type uses its own interface. For
example, the screen to modify a partner's data is not the same as the one to
modify an invoice.
Then, you have to know that the OpenERP user interface is dynamic, it means that it is not described "statically" by some code, but dynamically built from XML descriptions of the client screens.
Then, you have to know that the OpenERP user interface is dynamic, it means
that it is not described "statically" by some code, but dynamically built from
XML descriptions of the client screens.
From now on, we will call these screen descriptions views.
A notable characteristic of these views is that they can be edited at any moment (even during the program execution). After a modification to a displayed view has occurred, you simply need to close the tab corresponding to that 'view' and re-open it for the changes to appear.
A notable characteristic of these views is that they can be edited at any
moment (even during the program execution). After a modification to a displayed
view has occurred, you simply need to close the tab corresponding to that
'view' and re-open it for the changes to appear.
Views principles
++++++++++++++++
@ -36,111 +47,93 @@ The field disposition in a form view always follows the same principle. Fields a
* Fields are placed on the screen from left to right, and from top to bottom, according to the order in which they are declared in the view.
* Every screen is divided into 4 columns, each column being able to contain either a label, or an "edition" field. As every edition field is preceded (by default) by a label with its name, there will be two fields (and their respective labels) on each line of the screen. The green and red zones on the screen-shot below, illustrate those 4 columns. They designate respectively the labels and their corresponding fields.
.. figure:: images/sale_order.png
:scale: 50
:align: center
.. .. figure:: images/sale_order.png
.. :scale: 50
.. :align: center
Views also support more advanced placement options:
* A view field can use several columns. For example, on the screen-shot below, the zone in the blue frame is, in fact, the only field of a "one to many". We will come back later on this note, but let's note that it uses the whole width of the screen and not only one column.
.. figure:: images/sale_order_sale_order_lines.png
:scale: 50
:align: center
.. .. figure:: images/sale_order_sale_order_lines.png
.. :scale: 50
.. :align: center
* We can also make the opposite operation: take a columns group and divide it in as many columns as desired. The surrounded green zones of the screen above are good examples. Precisely, the green framework up and on the right side takes the place of two columns, but contains 4 columns.
As we can see below in the purple zone of the screen, there is also a way to distribute the fields of an object on different tabs.
.. figure:: images/sale_order_notebook.png
:scale: 50
:align: center
.. .. figure:: images/sale_order_notebook.png
.. :scale: 50
.. :align: center
On Change
+++++++++
The on_change attribute defines a method that is called when the content of a view field has changed.
This method takes at least arguments: cr, uid, ids, which are the three classical arguments and also the context dictionary. You can add parameters to the method. They must correspond to other fields defined in the view, and must also be defined in the XML with fields defined this way::
<field name="name_of_field" on_change="name_of_method(other_field'_1_', ..., other_field'_n_')"/>
The example below is from the sale order view.
You can use the 'context' keyword to access data in the context that can be used as params of the function.::
<field name="shop_id" on_change="onchange_shop_id(shop_id)"/>
.. code-block:: python
def onchange_shop_id(self, cr, uid, ids, shop_id):
v={}
if shop_id:
shop=self.pool.get('sale.shop').browse(cr,uid,shop_id)
v['project_id']=shop.project_id.id
if shop.pricelist_id.id:
v['pricelist_id']=shop.pricelist_id.id
v['payment_default_id']=shop.payment_default_id.id
return {'value':v}
When editing the shop_id form field, the onchange_shop_id method of the sale_order object is called and returns a dictionary where the 'value' key contains a dictionary of the new value to use in the 'project_id', 'pricelist_id' and 'payment_default_id' fields.
Note that it is possible to change more than just the values of
fields. For example, it is possible to change the value of some fields
and the domain of other fields by returning a value of the form:
return {'domain': d, 'value': value}
:returns: a dictionary with any mix of the following keys:
``domain``
A mapping of ``{field: domain}``.
The returned domains should be set on the fields instead of the
default ones.
``value``
A mapping of ``{field: value}}``, the values will be set on the
corresponding fields and may trigger new onchanges or attrs
changes
``warning`` A dict with the keys ``title`` and ``message``. Both
are mandatory. Indicate that an error message should be
displayed to the user.
Tree views
-----------
----------
These views are used when we work in list mode (in order to visualize several resources at once) and in the search screen. These views are simpler than the form views and thus have less options.
.. figure:: images/tree_view.png
:scale: 50
:align: center
Graph views
--------------
A graph is a new mode of view for all views of type form. If, for example, a sale order line must be visible as list or as graph, define it like this in the action that open this sale order line. Do not set the view mode as "tree,form,graph" or "form,graph" - it must be "graph,tree" to show the graph first or "tree,graph" to show the list first. (This view mode is extra to your "form,tree" view and should have a separate menu item):
.. code-block:: xml
<field name="view_type">form</field>
<field name="view_mode">tree,graph</field>
view_type::
tree = (tree with shortcuts at the left), form = (switchable view form/list)
view_mode::
tree,graph : sequences of the views when switching
Then, the user will be able to switch from one view to the other. Unlike forms and trees, OpenERP is not able to automatically create a view on demand for the graph type. So, you must define a view for this graph:
.. code-block:: xml
<record model="ir.ui.view" id="view_order_line_graph">
<field name="name">sale.order.line.graph</field>
<field name="model">sale.order.line</field>
<field name="type">graph</field>
<field name="arch" type="xml">
<graph string="Sales Order Lines">
<field name="product_id" group="True"/>
<field name="price_unit" operator="*"/>
</graph>
</field>
</record>
The graph view
A view of type graph is just a list of fields for the graph.
Graph tag
++++++++++
The default type of the graph is a pie chart - to change it to a barchart change **<graph string="Sales Order Lines">** to **<graph string="Sales Order Lines" type="bar">** You also may change the orientation.
:Example :
.. code-block:: xml
<graph string="Sales Order Lines" orientation="horizontal" type="bar">
Field tag
+++++++++
The first field is the X axis. The second one is the Y axis and the optional third one is the Z axis for 3 dimensional graphs. You can apply a few attributes to each field/axis:
* **group**: if set to true, the client will group all item of the same value for this field. For each other field, it will apply an operator
* **operator**: the operator to apply is another field is grouped. By default it's '+'. Allowed values are:
+ +: addition
+ \*: multiply
+ \**: exponent
+ min: minimum of the list
+ max: maximum of the list
:Defining real statistics on objects:
The easiest method to compute real statistics on objects is:
1. Define a statistic object which is a postgresql view
2. Create a tree view and a graph view on this object
You can get en example in all modules of the form: report\_.... Example: report_crm.
.. .. figure:: images/tree_view.png
.. :scale: 50
.. :align: center
Search views
--------------
@ -149,9 +142,9 @@ Search views are a new feature of OpenERP supported as of version 6.0
It creates a customized search panel, and is declared quite similarly to a form view,
except that the view type and root element change to ``search`` instead of ``form``.
.. image:: images/search.png
:scale: 50
:align: center
.. .. image:: images/search.png
.. :scale: 50
.. :align: center
Following is the list of new elements and features supported in search views.
@ -309,9 +302,9 @@ combining them with AND/OR operators. It is also possible to save any search con
of all currently applied domain and context values) as a personal filter, which can be recalled
at any time. Filters can also be turned into Shortcuts directly available in the User's homepage.
.. image:: images/filter.png
:scale: 50
:align: center
.. .. image:: images/filter.png
.. :scale: 50
.. :align: center
In above screenshot we filter Partner where Salesman = Demo user and Country = Belgium,
@ -320,6 +313,82 @@ We can save this search criteria as a Shortcut or save as Filter.
Filters are user specific and can be modified via the Manage Filters option in the filters drop-down.
Graph views
-----------
A graph is a new mode of view for all views of type form. If, for example, a sale order line must be visible as list or as graph, define it like this in the action that open this sale order line. Do not set the view mode as "tree,form,graph" or "form,graph" - it must be "graph,tree" to show the graph first or "tree,graph" to show the list first. (This view mode is extra to your "form,tree" view and should have a separate menu item):
.. code-block:: xml
<field name="view_type">form</field>
<field name="view_mode">tree,graph</field>
view_type::
tree = (tree with shortcuts at the left), form = (switchable view form/list)
view_mode::
tree,graph : sequences of the views when switching
Then, the user will be able to switch from one view to the other. Unlike forms and trees, OpenERP is not able to automatically create a view on demand for the graph type. So, you must define a view for this graph:
.. code-block:: xml
<record model="ir.ui.view" id="view_order_line_graph">
<field name="name">sale.order.line.graph</field>
<field name="model">sale.order.line</field>
<field name="type">graph</field>
<field name="arch" type="xml">
<graph string="Sales Order Lines">
<field name="product_id" group="True"/>
<field name="price_unit" operator="*"/>
</graph>
</field>
</record>
The graph view
A view of type graph is just a list of fields for the graph.
Graph tag
++++++++++
The default type of the graph is a pie chart - to change it to a barchart change **<graph string="Sales Order Lines">** to **<graph string="Sales Order Lines" type="bar">** You also may change the orientation.
:Example :
.. code-block:: xml
<graph string="Sales Order Lines" orientation="horizontal" type="bar">
Field tag
+++++++++
The first field is the X axis. The second one is the Y axis and the optional third one is the Z axis for 3 dimensional graphs. You can apply a few attributes to each field/axis:
* **group**: if set to true, the client will group all item of the same value for this field. For each other field, it will apply an operator
* **operator**: the operator to apply is another field is grouped. By default it's '+'. Allowed values are:
+ +: addition
+ \*: multiply
+ \**: exponent
+ min: minimum of the list
+ max: maximum of the list
:Defining real statistics on objects:
The easiest method to compute real statistics on objects is:
1. Define a statistic object which is a postgresql view
2. Create a tree view and a graph view on this object
You can get en example in all modules of the form: report\_.... Example: report_crm.
Calendar Views
--------------
@ -373,15 +442,15 @@ Screenshots
Month Calendar:
.. figure:: images/calendar_month.png
:scale: 50%
:align: center
.. .. figure:: images/calendar_month.png
.. :scale: 50%
.. :align: center
Week Calendar:
.. figure:: images/calendar_week.png
:scale: 50%
:align: center
.. .. figure:: images/calendar_week.png
.. :scale: 50%
.. :align: center
Gantt Views
@ -489,9 +558,9 @@ end time can be changed by dragging right end of a bar.
Screenshots
+++++++++++
.. figure:: images/gantt.png
:scale: 50%
:align: center
.. .. figure:: images/gantt.png
.. :scale: 50%
.. :align: center
Design Elements
@ -1270,9 +1339,9 @@ The *view_id* method works very well for menus/actions, but how can you specify
field, for example? When you have a one2many field, two views are used, a tree view (**in blue**), and a form view when
you click on the add button (**in red**).
.. figure:: images/one2many_views.png
:scale: 70%
:align: center
.. .. figure:: images/one2many_views.png
.. :scale: 70%
.. :align: center
When you add a one2many field in a form view, you do something like this :
@ -1367,62 +1436,3 @@ flexible if you define the child views separately and then specify which child
view to use as part of the one2many field.
Events
------
On Change
+++++++++
The on_change attribute defines a method that is called when the content of a view field has changed.
This method takes at least arguments: cr, uid, ids, which are the three classical arguments and also the context dictionary. You can add parameters to the method. They must correspond to other fields defined in the view, and must also be defined in the XML with fields defined this way::
<field name="name_of_field" on_change="name_of_method(other_field'_1_', ..., other_field'_n_')"/>
The example below is from the sale order view.
You can use the 'context' keyword to access data in the context that can be used as params of the function.::
<field name="shop_id" on_change="onchange_shop_id(shop_id)"/>
.. code-block:: python
def onchange_shop_id(self, cr, uid, ids, shop_id):
v={}
if shop_id:
shop=self.pool.get('sale.shop').browse(cr,uid,shop_id)
v['project_id']=shop.project_id.id
if shop.pricelist_id.id:
v['pricelist_id']=shop.pricelist_id.id
v['payment_default_id']=shop.payment_default_id.id
return {'value':v}
When editing the shop_id form field, the onchange_shop_id method of the sale_order object is called and returns a dictionary where the 'value' key contains a dictionary of the new value to use in the 'project_id', 'pricelist_id' and 'payment_default_id' fields.
Note that it is possible to change more than just the values of
fields. For example, it is possible to change the value of some fields
and the domain of other fields by returning a value of the form:
return {'domain': d, 'value': value}
:returns: a dictionary with any mix of the following keys:
``domain``
A mapping of ``{field: domain}``.
The returned domains should be set on the fields instead of the
default ones.
``value``
A mapping of ``{field: value}}``, the values will be set on the
corresponding fields and may trigger new onchanges or attrs
changes
``warning`` A dict with the keys ``title`` and ``message``. Both
are mandatory. Indicate that an error message should be
displayed to the user.

View File

@ -1,3 +1,5 @@
.. _module-dev-actions:
=================
Menus and Actions
=================
@ -133,6 +135,9 @@ The view describes how the edition form or the data tree/list appear on screen.
A form can be called by an action opening in 'Tree' mode. The form view is generally opened from the list mode (like if the user pushes on 'switch view').
.. _domain:
.. _domains:
The domain
----------
@ -207,9 +212,9 @@ They indicate at the user that he has to open a new window in a new 'tab'.
Administration > Custom > Low Level > Base > Action > Window Actions
.. figure:: images/module_base_action_window.png
:scale: 85
:align: center
.. .. figure:: images/module_base_action_window.png
.. :scale: 85
.. :align: center
Examples of actions
+++++++++++++++++++

View File

@ -1,3 +1,4 @@
.. _module-dev-example:
==========================
Example of module creation

View File

@ -1,3 +1,4 @@
.. _module-dev-versioning:
.. _module_versioning:
=================

View File

@ -1,3 +1,5 @@
.. _security:
==================================
Security in OpenERP: users, groups
==================================
@ -139,10 +141,6 @@ for users who do not belong to the authorized groups:
.. note:: The tests related to this feature are in ``openerp/tests/test_acl.py``.
.. warning:: At the time of writing the implementation of this feature is partial
and does not yet restrict read/write RPC access to the field.
The corresponding test is written already but currently disabled.
Workflow transition rules
+++++++++++++++++++++++++

View File

@ -10,3 +10,4 @@ Miscellanous
06_misc_need_action_specs.rst
06_misc_user_img_specs.rst
06_misc_import.rst
06_misc_auto_join.rst

75
doc/06_misc_auto_join.rst Normal file
View File

@ -0,0 +1,75 @@
.. _performing_joins_in_select:
Perfoming joins in select
=========================
.. versionadded:: 7.0
Starting with OpenERP 7.0, an ``auto_join`` attribute is added on *many2one* and
*one2many* fields. The purpose is to allow the automatic generation of joins in
select queries. This attribute is set to False by default, therefore not changing
the default behavior. Please note that we consider this feature as still experimental
and should be used only if you understand its limitations and targets.
Without ``_auto_join``, the behavior of expression.parse() is the same as before.
Leafs holding a path beginning with many2one or one2many fields perform a search
on the relational table. The result is then used to replace the leaf content.
For example, if you have on res.partner a domain like ``[('bank_ids.name',
'like', 'foo')]`` with bank_ids linking to res.partner.bank, 3 queries will be
performed :
- 1 on res_partner_bank, with domain ``[('name', '=', 'foo')]``, that returns a
list of res.partner.bank ids (bids)
- 1 on res_partner, with a domain ``['bank_ids', 'in', bids)]``, that returns a
list of res.partner ids (pids)
- 1 on res_partner, with a domain ``[('id', 'in', pids)]``
When the ``auto_join`` attribute is True on a relational field, the destination
table will be joined to produce only one query.
- the relational table is accessed using an alias: ``'"res_partner_bank"
as res_partner__bank_ids``. The alias is generated using the relational field
name. This allows to have multiple joins with different join conditions on the
same table, depending on the domain.
- there is a join condition between the destination table and the main table:
``res_partner__bank_ids."partner_id"=res_partner."id"``
- the condition is then written on the relational table:
``res_partner__bank_ids."name" = 'foo'``
This manipulation is performed in expression.parse(). It checks leafs that
contain a path, i.e. any domain containing a '.'. It then checks whether the
first item of the path is a *many2one* or *one2many* field with the ``auto_join``
attribute set. If set, it adds a join query and recursively analyzes the
remaining of the leaf, using the same behavior. If the remaining path also holds
a path with auto_join fields, it will add all tables and add every necessary
join conditions.
Chaining joins allows to reduce the number of queries performed, and to avoid
having too long equivalent leaf replacement in domains. Indeed, the internal
queries produced by this behavior can be very costly, because they were generally
select queries without limit that could lead to huge ('id', 'in', [...])
leafs to analyze and execute.
Some limitations exist on this feature that limits its current use as of version
7.0. **This feature is therefore considered as experimental, and used
to speedup some precise bottlenecks in OpenERP**.
List of known issues and limitations:
- using ``auto_join`` bypasses the business logic; no name search is performed,
only direct matches between ids using join conditions
- ir.rules are not taken into account when analyzing and adding the join
conditions
List of already-supported corner cases :
- one2many fields having a domain attribute. Static domains as well as dynamic
domain are supported
- auto_join leading to functional searchable fields
Typical use in OpenERP 7.0:
- in mail module: notification_ids field on mail_message, allowing to speedup
the display of the various mailboxes
- in mail module: message_ids field on mail_thread, allowing to speedup the
display of needaction counters and documents having unread messages

View File

@ -76,9 +76,9 @@ This phase also generates the ``rows`` indexes for any
Conversion
++++++++++
This second phase takes the record dicts, extracts the :ref:`dbid` and
:ref:`xid` if present and attempts to convert each field to a type
matching what OpenERP expects to write.
This second phase takes the record dicts, extracts the :term:`database
ID` and :term:`external ID` if present and attempts to convert each
field to a type matching what OpenERP expects to write.
* Empty fields (empty strings) are replaced with the ``False`` value
@ -141,14 +141,14 @@ If ``name_search`` finds no value, an error is generated. If
``name_search`` finds multiple value, a warning is generated to warn
the user of ``name_search`` collisions.
If the specified field is a :ref:`xid` (``m2o/id``), the
If the specified field is a :term:`external ID` (``m2o/id``), the
corresponding record it looked up in the database and used as the
field's value. If no record is found matching the provided external
ID, an error is generated.
If the specified field is a :ref:`dbid` (``m2o/.id``), the process is
the same as for external ids (on database identifiers instead of
external ones).
If the specified field is a :term:`database ID` (``m2o/.id``), the
process is the same as for external ids (on database identifiers
instead of external ones).
Many to Many field
~~~~~~~~~~~~~~~~~~
@ -161,11 +161,11 @@ One to Many field
~~~~~~~~~~~~~~~~~
For each o2m record extracted, if the record has a ``name``,
:ref:`xid` or :ref:`dbid` the :ref:`dbid` is looked up and checked
through the same process as for m2o fields.
:term:`external ID` or :term:`database ID` the :term:`database ID` is
looked up and checked through the same process as for m2o fields.
If a :ref:`dbid` was found, a LINK_TO command is emmitted, followed by
an UPDATE with the non-db values for the relational field.
If a :term:`database ID` was found, a LINK_TO command is emmitted,
followed by an UPDATE with the non-db values for the relational field.
Otherwise a CREATE command is emmitted.

34
doc/adding-command.rst Normal file
View File

@ -0,0 +1,34 @@
.. _adding-command:
Adding a new command
====================
``oe`` uses the argparse_ library to implement commands. Each
command lives in its own ``openerpcommand/<command>.py`` file.
.. _argparse: http://docs.python.org/2.7/library/argparse.html
To create a new command, probably the most simple way to get started is to
copy/paste an existing command, say ``openerpcommand/initialize.py`` to
``openerpcommand/foo.py``. In the newly created file, the important bits
are the ``run(args)`` and ``add_parser(subparsers)`` functions.
``add_parser``'s responsability is to create a (sub-)parser for the command,
i.e. describe the different options and flags. The last thing it does is to set
``run`` as the function to call when the command is invoked.
.. code-block:: python
> def add_parser(subparsers):
> parser = subparsers.add_parser('<command-name>',
> description='...')
> parser.add_argument(...)
> ...
> parser.set_defaults(run=run)
``run(args)`` actually implements the command. It should be kept as simple as
possible and delegate most of its work to small functions (probably placed at
the top of the new file). In other words, its responsability is mainly to
deal with the presence/absence/pre-processing of ``argparse``'s arguments.
Finally, the module must be added to ``openerpcommand/__init__.py``.

23
doc/changelog.rst Normal file
View File

@ -0,0 +1,23 @@
.. _changelog:
Changelog
=========
`trunk`
-------
- Almost removed ``LocalService()``. For reports,
``openerp.osv.orm.Model.print_report()`` can be used. For workflows, see
:ref:`orm-workflows`.
- Removed support for the ``NET-RPC`` protocol.
- Added the :ref:`Long polling <longpolling-worker>` worker type.
- Added :ref:`orm-workflows` to the ORM.
- Added :ref:`routing-decorators` to the RPC and WSGI stack.
- Removed support for ``__terp__.py`` descriptor files.
- Removed support for ``<terp>`` root element in XML files.
- Removed support for the non-openerp namespace (e.g. importing ``tools``
instead of ``openerp.tools`` in an addons).
- Add a new type of exception that allows redirections:
``openerp.exceptions.RedirectWarning``.
- Give a pair of new methods to ``res.config.settings`` and a helper to make
them easier to use: ``get_config_warning()``.

40
doc/commands.rst Normal file
View File

@ -0,0 +1,40 @@
.. _commands:
Available commands
==================
This page explain some of the available ``oe`` commands. For an overview about
``oe``, see :doc:`openerp-command`.
Keep in mind that ``oe --help`` and ``oe <command> --help`` already give a lot
of information about the commands and their options and flags.
``web``
-------
The ``web`` command is used to create a single OpenERP server process to handle
regular HTTP requests and XML-RPC requests. It is possible to execute such
process multiple times, possibly on different machines.
It is possible to chose the ``--threaded`` or ``--gevent`` flags. It is
recommanded to use ``--threaded`` only when running a single process.
``--gevent`` is experimental; it is planned to use it for the embedded chat
feature.
Example invocation::
> oe web --addons ../../addons/trunk:../../web/trunk/addons --threaded
``cron``
--------
The ``cron`` command is used to create a single OpenERP process to execute
so-called cron jobs, also called scheduled tasks in the OpenERP interface. As
for the ``web`` command, multiple cron processes can be run side by side.
It is necessary to specify on the command-line which database need to be
watched by the cron process with the ``--database`` option.
Example invocation::
> oe cron --addons ../../addons/trunk:../../web/trunk/addons --database production

256
doc/conf.py Normal file
View File

@ -0,0 +1,256 @@
# -*- coding: utf-8 -*-
#
# OpenERP Technical Documentation configuration file, created by
# sphinx-quickstart on Fri Feb 17 16:14:06 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.append(os.path.abspath('_themes'))
sys.path.append(os.path.abspath('..'))
sys.path.append(os.path.abspath('../openerp'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.viewcode']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'OpenERP Server Developers Documentation'
copyright = u'2012, OpenERP s.a.'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '7.0'
# The full version, including alpha/beta/rc tags.
release = '7.0b'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'flask'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_themes']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
html_sidebars = {
'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html'],
'**': ['sidebarlogo.html', 'localtoc.html', 'relations.html',
'sourcelink.html', 'searchbox.html']
}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'openerp-server-doc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'openerp-server-doc.tex', u'OpenERP Server Developers Documentation',
u'OpenERP s.a.', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'openerp-server-doc', u'OpenERP Server Developers Documentation',
[u'OpenERP s.a.'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'OpenERPServerDocumentation', u'OpenERP Server Developers Documentation',
u'OpenERP s.a.', 'OpenERPServerDocumentation', 'Developers documentation for the openobject-server project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'python': ('http://docs.python.org/', None),
'openerpweb': ('http://doc.openerp.com/trunk/developers/web', None),
}

View File

@ -16,20 +16,20 @@ Summary
Configuring and starting an OpenERP server with Gunicorn is straightfoward. The
different sections below give more details but the following steps are all it
takes::
takes:
1. Use a configuration file, passing it to ``gunicorn`` using the ``-c``
option.
2. Within the same configuration file, also configure OpenERP.
3. Run ``gunicorn openerp:wsgi.core.application -c gunicorn.conf.py``.
1. Use a configuration file, passing it to ``gunicorn`` using the ``-c``
option.
2. Within the same configuration file, also configure OpenERP.
3. Run ``gunicorn openerp:service.wsgi_server.application -c openerp-wsgi.py``.
Sample configuration file
-------------------------
A sample ``gunicorn.conf.py`` configuration file for Gunicorn can be found in
the OpenERP server source tree. It is fairly well commented and easily
A sample ``openerp-wsgi.py`` configuration file for WSGI servers can be found
in the OpenERP server source tree. It is fairly well commented and easily
customizable for your own usage. While reading the remaining of this page, it
is advised you take a look at the sample ``gunicorn.conf.py`` file as it makes
is advised you take a look at the sample ``openerp-wsgi.py`` file as it makes
things easier to follow.
Configuration
@ -37,7 +37,7 @@ Configuration
Gunicorn can be configured by a configuration file and/or command-line
arguments. For a list of available options, you can refer to the official
Gunicorn documentation http://gunicorn.org/configure.html.
Gunicorn documentation http://docs.gunicorn.org/en/latest/configure.html.
When the OpenERP server is started on its own, by using the ``openerp-server``
script, it can also be configured by a configuration file or its command-line
@ -46,7 +46,7 @@ as the Gunicorn configuration file is a full-fledged Python file, we can
``import openerp`` in it and configure directly the server.
The principle can be summarized with this three lines (although they are spread
across the whole sample ``gunicorn.conf.py`` file)::
across the whole sample ``openerp-wsgi.py`` file)::
import openerp
conf = openerp.tools.config
@ -57,45 +57,16 @@ containing the OpenERP server implementation). The second one is really to
shorten repeated usage of the same variable. The third one sets a parameter, in
this case the equivalent of the ``--addons-path`` command-line option.
Finally, Gunicorn offers a few hooks so we can call our own code at some points
in its execution. The most important one is the ``on_starting`` hook. It lets
us properly initialize the ``openerp`` library before Gunicorn starts handling
requests. ``pre_request`` and ``post_request`` are called before and after
requests are handled. We provide functions in ``openerp.wsgi.core`` that can be
used to define those hooks: a typical Gunicorn configuration for OpenERP will
thus contains::
on_starting = openerp.wsgi.core.on_starting
pre_request = openerp.wsgi.core.pre_request
post_request = openerp.wsgi.core.post_request
Running
-------
Once a proper configuration file is available, running the OpenERP server with
Gunicorn can be done with the following command::
> gunicorn openerp:wsgi.core.application -c gunicorn.conf.py
> gunicorn openerp:service.wsgi_server.application -c openerp-wsgi.py
``openerp`` must be importable by Python. The simplest way is to run the above
command from the server source directory (i.e. the directory containing the
``openerp`` module). Alternatively, the module can be installed on your machine
as a regular Python library or added to your ``PYTHONPATH``.
Running behind a reverse proxy
------------------------------
If you intend to run Gunicorn behind a reverse proxy (nginx_ is recommended),
an alternative entry point is available in ``openerp.wsgi.proxied``. That entry
point uses werkzeug's ProxyFix_ class to set a few headers. You first have to
explicitely import that sub-module if you want to use it. So add this line in
the configuration file::
import openerp.wsgi.proxied
and then adapt the command-line::
> gunicorn openerp:wsgi.proxied.application -c gunicorn.conf.py
.. _nginx: http://nginx.org/en/
.. _ProxyFix: http://werkzeug.pocoo.org/docs/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix

View File

@ -0,0 +1,73 @@
.. _using-mod-wsgi:
Deploying with ``mod_wsgi``
===========================
``mod_wsgi`` makes it possible to run a WSGI_ application (such as OpenERP)
under the Apache_ HTTP server.
.. _WSGI: http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface
.. _Apache: https://httpd.apache.org/
Summary
-------
Similarly to :doc:`deployment-gunicorn`, running OpenERP behind Apache with
``mod_wsgi`` requires to modify the sample ``openerp-wsgi.py`` script. Then
that Python script can be set in the Apache configuration.
Python (WSGI) application
-------------------------
Apache needs a Python script providing the WSGI application. By default the
symbol looked up by Apache is ``application`` but it can be overidden with the
``WSGICallableObject`` directive if necessary. A sample script
``openerp-wsgi.py`` is provided with OpenERP and you can adapt it to your
needs. For instance, make sure to correctly set the ``addons_path``
configuration (using absolute paths).
.. note ::
The script provided to Apache has often the extension ``.wsgi`` but the
``openerp-wsgi.py`` script will do just as fine.
Apache Configuration
--------------------
In Apache's configuration, add the following line to activate ``mod_wsgi``::
LoadModule wsgi_module modules/mod_wsgi.so
Then a possible (straightforward, with e.g. no virtual server) configuration is
as follow::
WSGIScriptAlias / /home/thu/repos/server/trunk/openerp-wsgi.py
WSGIDaemonProcess oe user=thu group=users processes=2 python-path=/home/thu/repos/server/trunk/ display-name=apache-openerp
WSGIProcessGroup oe
<Directory /home/thu/repos/server/trunk>
Order allow,deny
Allow from all
</Directory>
The ``WSGIScriptAlias`` directive indicates that any URL matching ``/`` will
run the application defined in the ``openerp-wsgi.py`` script.
The ``WSGIDaemonProcess`` and ``WSGIProcessGroup`` directives create a process
configuration. The configuration makes it possible for isntance to specify
which user runs the OpenERP process. The ``display-name`` option will make the
processes appear as ``apache-openerp`` in ``ps`` (instead of the normal
``httpd``).
Finally, it is necessary to make sure the source directory where the script can
be found is allowed by Apache with the ``Directory`` block.
``mod_wsgi`` supports a lot of directives, please see this ``mod_wsgi`` wiki
page for more details:
http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives.
Running
-------
When the Apache configuration changes, it is necessary to restart Apache, e.g. with::
/etc/init.d/httpd restart

View File

@ -0,0 +1,303 @@
.. _form-view-guidelines:
Form Views Guidelines
=====================
Authors: Aline Preillon, Raphael Collet
This document presents functional and technical guidelines for
creating/organizing form views in OpenERP version 7.0. For each item, both the
functional and technical aspects are explained. The goal of the new style of
forms is to make OpenERP easier to use, and to guide users through the system.
Business Views
--------------
Business views are targeted at regular users, not advanced users. Examples
are: Opportunities, Products, Partners, Tasks, Projects, etc.
.. image:: /form-view-guidelines/oppreadonly.png
In general, a business view is composed of
1. a status bar on top (with technical or business flow),
2. a sheet in the middle (the form itself),
3. a bottom part with History and Comments.
Technically, the new form views are structured as follows in XML::
<form version=”7.0”>
<header> ... content of the status bar ... </header>
<sheet> ... content of the sheet ... </sheet>
<div class=”oe_chatter”> ... content of the bottom part ... </div>
</form>
The Status Bar
''''''''''''''
The purpose of the status bar is to show the status of the record and the
action buttons, which were formerly at the bottom of form views.
.. image:: /form-view-guidelines/status.png
The Buttons
...........
The order of buttons follows the business flow. For instance, in a sale order,
the logical steps are:
1. Send the quotation
2. Confirm the quotation
3. Create the final invoice
4. Send the goods
Highlighted buttons (in red) emphasize the logical next step, to help the user.
It is usually the first active button. On the other end, cancel buttons must
remain grey (normal). For instance, in Invoice, the button “Refund” must never
be red.
Technically, buttons are highlighted by adding the class “oe_highlight”::
<button class=”oe_highlight” name=”...” type=”...” states=”...”/>
The Status
..........
We use the widget “statusbar”, and the current value of the state is shown in
red. One should make visible the states that are common to all flows (for
instance, a sale order begins as a quotation, then we send it, then it becomes
a full sale order, and finally it is done.) Exceptions or states depending on
particular flow are only visible if it is the current one.
.. image:: /form-view-guidelines/status1.png
.. image:: /form-view-guidelines/status2.png
The states are shown following the order used in the field (the list in a
selection field, etc). States that are always visible are indicated by the
attribute statusbar_visible. One can also show some states in a specific color
with statusbar_colors.
::
<field name="state" widget="statusbar"
statusbar_visible="draft,sent,progress,invoiced,done"
statusbar_colors="{shipping_except:red,waiting_date:blue}"/>
The Sheet
'''''''''
All business views should look like a printed sheet:
.. image:: /form-view-guidelines/sheet.png
Technically, the layout of forms version 7.0 is different than former versions.
There is no longer a default “grid” layout; instead the layout is more based on
HTML and CSS. The following conventions are now used:
1. The elements <form> and <page> no longer define groups; the elements inside
are laid out inline. One should use explicit <div> or <group> to create
blocks.
2. By default, the element <group> now defines two columns inside, unless an
attribute col=”n” is used. The columns have the same width (1/n th of the
groups width). Use a <group> element to produce a column of fields.
3. The element <separator string=”XXX”/> on top of a group can be replaced
putting string=”XXX” inside the <group> element.
4. The element <field name=”XXX”/> does not produce a label, except when they
are directly below a <group> element. Use <label for=”XXX”/> to produce
the label of the field.
Sheet Headers
.............
Some sheets have headers with one or more fields, and the labels of those
fields are only shown in edit mode.
+---------------------------------------------+----------------------------------------------+
| View mode | Edit mode |
+---------------------------------------------+----------------------------------------------+
| .. image:: /form-view-guidelines/header.png | .. image:: /form-view-guidelines/header2.png |
+---------------------------------------------+----------------------------------------------+
Use HTML text, <div>, <h1>, <h2>… to produce nice headers, and <label> with the
CSS class “oe_edit_only” to produce the fields label in edit mode. Use the
CSS class “oe_inline” to produce inline fields (not blocks). The form above is
produced by the following XML.
::
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
<label for="planned_revenue" class="oe_edit_only"/>
<h2>
<field name="planned_revenue" class="oe_inline"/>
<field name="company_currency" class="oe_inline oe_edit_only"/> at
<field name="probability" class="oe_inline"/> % success rate
</h2>
Button Box
..........
Many relevant actions or links can be directly displayed in the form. For
example, in Opportunity form, the actions “Schedule a Call” and “Schedule a
Meeting” take an important place in the use of the CRM. Instead of placing
them in the “More” menu of the sidebar, put them directly in the sheet as
buttons (on the top right).
.. image:: /form-view-guidelines/header3.png
Technically, the buttons are placed inside a <div> to group them as a block on
the right-hand side of the sheet.
::
<div class="oe_button_box oe_right">
<button string="Schedule/Log Call" name="..." type="action"/>
<button string="Schedule Meeting" name="action_makeMeeting" type="object"/>
</div>
Groups and Titles
.................
A column of fields is now produced with a <group> element, with an optional
title. The title has the same effect as placing an explicit <separator>
element inside the group.
.. image:: /form-view-guidelines/screenshot-03.png
::
<group string="Payment Options">
<field name="writeoff_amount"/>
<field name="payment_option"/>
</group>
It is recommended to have two columns of fields on the form. For this, simply
put the <group> elements that contain the fields inside a <group> element.
To ease view inheritance, it is recommended to put a name=”...” in <group>
elements. Adding fields inside such a group is trivial.
Special Case: Subtotals
~~~~~~~~~~~~~~~~~~~~~~~
Some CSS classes are defined to render subtotals like in invoice forms:
.. image:: /form-view-guidelines/screenshot-00.png
::
<group class="oe_subtotal_footer">
<field name="amount_untaxed"/>
<field name="amount_tax"/>
<field name="amount_total" class="oe_subtotal_footer_separator"/>
<field name="residual" style="margin-top: 10px"/>
</group>
Placeholders and Inline Fields
..............................
Sometimes field labels make the form too complex. One can omit field labels,
and instead put a placeholder inside the field. The placeholder text is
visible only when the field is empty. The placeholder should tell what to
place inside the field, and not be an example.
One can also group fields together by rendering them “inline” inside an
explicit block element like <div>. This allows to group several elements in
place of a field (without its label).
The following example, taken from the Leads form, shows both placeholders and
inline fields (zip and city).
+--------------------------------------------------+----------------------------------------------------+
| Edit mode | View mode |
+--------------------------------------------------+----------------------------------------------------+
| .. image:: /form-view-guidelines/placeholder.png | .. image:: /form-view-guidelines/screenshot-01.png |
+--------------------------------------------------+----------------------------------------------------+
::
<group>
<label for="street" string="Address"/>
<div>
<field name="street" placeholder="Street..."/>
<field name="street2"/>
<div>
<field name="zip" class="oe_inline" placeholder="ZIP"/>
<field name="city" class="oe_inline" placeholder="City"/>
</div>
<field name="state_id" placeholder="State"/>
<field name="country_id" placeholder="Country"/>
</div>
</group>
Images
......
Images, like avatars, should be displayed on the right of the sheet. The
product form looks like:
.. image:: /form-view-guidelines/screenshot-02.png
The form above contains a <sheet> element that starts with::
<field name="product_image" widget="image" class="oe_avatar oe_right"/>
Tags
....
Many2many fields, like categories, are better rendered as a list of tags. Use
the widget “many2many_tags”:
.. image:: /form-view-guidelines/screenshot-04.png
::
<field name="category_id"
widget="many2many_tags"/>
Configuration Forms and Wizards
-------------------------------
Configuration Forms
'''''''''''''''''''
Examples of configuration forms: Stages, Leave Type, etc. This concerns all
menu items under Configuration of each application (like Sales/Configuration).
.. image:: /form-view-guidelines/nosheet.png
For those views, the guidelines are:
1. no header (because no state, no workflow, no button)
2. no sheet
Regular Wizards (Popup)
'''''''''''''''''''''''
Example: “Schedule a Call” from an opportunity.
.. image:: /form-view-guidelines/wizard-popup.png
The guidelines are:
1. avoid separators (the title is already in the popup title bar, so another
separator is not relevant);
2. avoid cancel buttons (user generally close the popup window to get the same
effect);
3. action buttons must be highlighted (red);
4. when there is a text area, use a placeholder instead of a label or a
separator;
5. like in regular form views, put buttons in the <header> element.
Configuration Wizard
''''''''''''''''''''
Example: Settings / Configuration / Sales. The guidelines are:
1. always in line (no popup);
2. no sheet;
3. keep the cancel button (users cannot close the window);
4. the button “Apply” must be red.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -16,7 +16,19 @@ OpenERP Server
04_security
05_test_framework
06_misc
09_deployment
deployment-gunicorn
deployment-mod-wsgi
form-view-guidelines
OpenERP Command
'''''''''''''''
.. toctree::
:maxdepth: 1
openerp-command.rst
commands.rst
adding-command.rst
OpenERP Server API
''''''''''''''''''
@ -24,8 +36,27 @@ OpenERP Server API
.. toctree::
:maxdepth: 1
api_core.rst
orm-methods.rst
api_models.rst
routing.rst
Changelog
'''''''''
.. toctree::
:maxdepth: 1
changelog.rst
Concepts
''''''''
.. glossary::
Database ID
The primary key of a record in a PostgreSQL table (or a
virtual version thereof), usually varies from one database to
the next.
External ID

66
doc/openerp-command.rst Normal file
View File

@ -0,0 +1,66 @@
.. _openerp-command:
The ``oe`` script
=================
The ``oe`` script provides a set of command-line tools around the OpenERP
framework. It is meant to replace the older ``openerp-server`` script (which
is still available).
Using ``oe``
------------
In contrast to the previous ``openerp-server`` script, ``oe`` defines a few
commands, each with its own set of flags and options. You can get some
information for any of them with
::
> oe <command> --help
For instance::
> oe run-tests --help
Some ``oe`` options can be provided via environment variables. For instance::
> export OPENERP_DATABASE=trunk
> export OPENERP_HOST=127.0.0.1
> export OPENERP_PORT=8069
Depending on your needs, you can group all of the above in one single script;
for instance here is a, say, ``test-trunk-view-validation.sh`` file::
COMMAND_REPO=/home/thu/repos/command/trunk/
SERVER_REPO=/home/thu/repos/server/trunk
export PYTHONPATH=$SERVER_REPO:$COMMAND_REPO
export PATH=$SERVER_REPO:$COMMAND_REPO:$PATH
export OPENERP_DATABASE=trunk
export OPENERP_HOST=127.0.0.1
export OPENERP_PORT=8069
# The -d ignored is actually needed by `oe` even though `test_view_validation`
# itself does not need it.
oe run-tests -d ignored -m openerp.test_view_validation
Available commands
-------------------
See the :doc:`commands` page.
Adding new commands
-------------------
See the :doc:`adding-command` page.
Bash completion
---------------
A preliminary ``oe-bash-completion`` file is provided. After sourcing it,
::
> . oe-bash-completion
completion (using the TAB character) in Bash should work.

61
doc/orm-methods.rst Normal file
View File

@ -0,0 +1,61 @@
.. _orm-methods:
ORM methods
===========
.. _orm-workflows:
Workflow-related methods
------------------------
.. versionadded:: 7.1
Creating, deleting, or otherwise manipulating workflow instances is possible
right from a Model instance. (Previously, workflows were handled throught a
call to ``LocalService('workflow')``. Using the ORM methods is now the preferred
way.)
.. currentmodule:: openerp.osv.orm
.. automethod:: BaseModel.create_workflow
:noindex:
This is used instead of ``LocalService('workflow').trg_create()``.
.. automethod:: BaseModel.delete_workflow
:noindex:
This is used instead of ``LocalService('workflow').trg_delete()``.
.. automethod:: BaseModel.step_workflow
:noindex:
This is used instead of ``LocalService('workflow').trg_write()``.
.. automethod:: BaseModel.redirect_workflow
:noindex:
.. automethod:: BaseModel.signal_workflow
:noindex:
This is used instead of ``LocalService('workflow').trg_validate()``.
.. method:: BaseModel.signal_xxx(cr, uid, ids)
:noindex:
Sends a signal ``xxx`` to the workflow instances bound to the given record
IDs. (This is implemented using ``__getattr__`` so no source link is
rendered on the right.)
This is used instead of ``LocalService('workflow').trg_validate()``.
.. note::
Low-level access to the workflows is still possible by using the
``openerp.workflow`` module, that is, in a similar way to what was possible
with the previous ``LocalService('workflow')`` access. This may be useful
when looking-up a model in the registry and/or its records is not necessary.
For instance when working with raw model names and record IDs is preferred (to
avoid hitting unnecessarily the database). But this is something that should be
carefully considered as it would bypass the ORM methods (and thus any inherited
behaviors).

View File

@ -0,0 +1,23 @@
.. _report-declaration:
Report declaration
==================
.. versionadded:: 7.1
Before version 7.1, report declaration could be done in two different ways:
either via a ``<report>`` tag in XML, or via such a tag and a class
instanciation in a Python module. Instanciating a class in a Python module was
necessary when a custom parser was used.
In version 7.1, the recommended way to register a report is to use only the
``<report>`` XML tag. The tag can now support an additional ``parser``
attribute. The value for that attibute must be a fully-qualified class name,
without the leading ``openerp.addons.`` namespace.
.. note::
The rational to deprecate the manual class instanciation is to make all
reports visible in the database, have a unique way to declare reports
instead of two, and remove the need to maintain a registry of reports in
memory.

29
doc/routing.rst Normal file
View File

@ -0,0 +1,29 @@
.. _routing:
Routing
=======
.. versionchanged:: 7.1
The OpenERP framework, as an HTTP server, serves a few hard-coded URLs
(``models``, ``db``, ...) to expose RPC endpoints. When running the web addons
(which is almost always the case), it also serves URLs without them being RPC
endpoints.
In older version of OpenERP, adding RPC endpoints was done by subclassing the
``openerp.netsvc.ExportService`` class. Adding WSGI handlers was done by
registering them with the :py:func:`openerp.wsgi.register_wsgi_handler`
function.
Starting with OpenERP 7.1, exposing a new arbitrary WSGI handler is done with
the :py:func:`openerp.http.handler` decorator while adding an RPC endpoint is
done with the :py:func:`openerp.http.rpc` decorator.
.. _routing-decorators:
Routing decorators
------------------
.. automodule:: openerp.http
:members:
:undoc-members:

View File

@ -80,17 +80,6 @@ specify the certificate file for the SSL connection
\fB\-\-pkey\-file\fR=\fISECURE_PKEY_FILE\fR
specify the private key file for the SSL connection
.IP
NET\-RPC Configuration:
.TP
\fB\-\-netrpc\-interface\fR=\fINETRPC_INTERFACE\fR
specify the TCP IP address for the NETRPC protocol
.TP
\fB\-\-netrpc\-port\fR=\fINETRPC_PORT\fR
specify the TCP port for the NETRPC protocol
.TP
\fB\-\-no\-netrpc\fR
disable the NETRPC protocol
.IP
Static HTTP service:
.TP
\fB\-\-static\-http\-enable\fR

5
oe Executable file
View File

@ -0,0 +1,5 @@
#! /usr/bin/env python2
if __name__ == '__main__':
import openerpcommand.main
openerpcommand.main.run()

89
oe-bash-completion Normal file
View File

@ -0,0 +1,89 @@
_oe()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
cmd="${COMP_WORDS[0]}"
subcmd=""
if [[ ${COMP_CWORD} > 0 ]] ; then
subcmd="${COMP_WORDS[1]}"
fi
# oe
opts="initialize model read run-tests scaffold update \
call open show consume-nothing consume-memory leak-memory \
consume-cpu bench-read bench-fields-view-get bench-dummy bench-login \
bench-sale-mrp --help"
if [[ ${prev} == oe && ${cur} != -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# oe call
opts="--database --user --password --host --port --help"
if [[ ${subcmd} == call ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# oe initialize
opts="--database --addons --all-modules --exclude --no-create --help"
if [[ ${subcmd} == initialize ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# oe model
opts="--database --model --field --verbose --help"
if [[ ${subcmd} == model ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# oe read
opts="--database --model --id --field --verbose --short --help"
if [[ ${subcmd} == read ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# oe run-tests
opts="--database --addons --module --dry-run --help"
if [[ ${subcmd} == run-tests ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# oe scaffold
opts="--help"
if [[ ${subcmd} == scaffold ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# fallback for unimplemented completion
opts="--help"
if [[ true ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -F _oe oe

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

@ -1 +0,0 @@
excludes: pychart release openerp-server test run_tests addons/base_quality_interrogation

View File

@ -13,6 +13,6 @@ Description: OpenERP is a complete ERP and CRM. The main features are accounting
and financial), stock management, sales and purchases management, tasks
automation, marketing campaigns, help desk, POS, etc. Technical features include
a distributed server, flexible workflows, an object database, a dynamic GUI,
customizable reports, and NET-RPC and XML-RPC interfaces.
customizable reports, and an XML-RPC interface.
Keywords: ERP, Accounting, Stock, CRM, Enterprise, Logistics, Management, Sales, Purchases
Platform: Linux, Win32

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@ -15,18 +15,31 @@
# 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/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
""" OpenERP core library.
""" OpenERP core library..
"""
# Make sure the OpenERP server runs in UTC. This is especially necessary
# under Windows as under Linux it seems the real import of time is
# sufficiently deferred so that setting the TZ environment variable
# in openerp.cli.server was working.
import os
os.environ['TZ'] = 'UTC' # Set the timezone...
import time # ... *then* import time.
del os
del time
# The hard-coded super-user id (a.k.a. administrator, or root user).
SUPERUSER_ID = 1
import addons
import cli
import conf
import http
import loglevels
import modules
import netsvc
@ -34,12 +47,9 @@ import osv
import pooler
import release
import report
import run_tests
import service
import sql_db
import test
import tools
import wizard
import workflow
# backward compatilbility
# TODO: This is for the web addons, can be removed later.
@ -51,6 +61,15 @@ wsgi.register_wsgi_handler = wsgi.wsgi_server.register_wsgi_handler
# its own copy of the data structure and we don't need to care about
# locks between threads.
multi_process = False
# Is the server running with gevent.
evented = False
def registry(database_name):
"""
Return the model registry for the given database. If the registry does not
exist yet, it is created on the fly.
"""
return modules.registry.RegistryManager.get(database_name)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
# Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -80,12 +80,12 @@ 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',
'security/base_security.xml',
'security/ir.model.access.csv',
'security/ir.model.access-1.csv', # res.partner.address is deprecated; it is still there for backward compability only and will be removed in next version
],
'demo': [
'base_demo.xml',
@ -94,19 +94,17 @@ The kernel of OpenERP, needed for all installation.
'res/res_partner_image_demo.xml',
],
'test': [
'test/base_test.xml',
'test/base_test.yml',
'test/test_context.xml',
'test/bug_lp541545.xml',
'test/test_osv_expression.yml',
'test/test_ir_rule.yml', # <-- These tests modify/add/delete ir_rules.
# Commented because this takes some time.
# This must be (un)commented with the corresponding import statement
# in test/__init__.py.
# 'test/test_ir_cron.yml', # <-- These tests perform a roolback.
],
'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:

View File

@ -149,8 +149,6 @@ CREATE TABLE res_users (
active boolean default True,
login varchar(64) NOT NULL UNIQUE,
password varchar(64) default null,
tz varchar(64) default null,
lang varchar(64) default '',
-- No FK references below, will be added later by ORM
-- (when the destination rows exist)
company_id int,
@ -317,13 +315,29 @@ CREATE TABLE ir_module_module_dependency (
primary key(id)
);
CREATE TABLE res_company (
CREATE TABLE res_partner (
id serial NOT NULL,
name character varying(64) not null,
parent_id integer references res_company on delete set null,
name character varying(128),
lang varchar(64),
company_id int,
primary key(id)
);
CREATE TABLE res_currency (
id serial PRIMARY KEY,
name VARCHAR(32) NOT NULL
);
CREATE TABLE res_company (
id serial PRIMARY KEY,
name character varying(128) not null,
parent_id integer references res_company on delete set null,
partner_id integer not null references res_partner,
currency_id integer not null references res_currency
);
CREATE TABLE res_lang (
id serial PRIMARY KEY,
name VARCHAR(64) NOT NULL UNIQUE,
@ -376,16 +390,24 @@ CREATE TABLE ir_model_relation (
module integer NOT NULL references ir_module_module on delete restrict,
model integer NOT NULL references ir_model on delete restrict,
name character varying(128) NOT NULL
);
);
---------------------------------
-- Users
---------------------------------
insert into res_users (id,login,password,active,company_id,partner_id) VALUES (1,'admin','admin',true,1,1);
insert into ir_model_data (name,module,model,noupdate,res_id) VALUES ('user_root','base','res.users',true,1);
insert into res_users (id,login,password,active,company_id,partner_id,lang) values (1,'admin','admin',True,1,1,'en_US');
insert into ir_model_data (name,module,model,noupdate,res_id) values ('user_root','base','res.users',True,1);
insert into res_partner (id, name, lang, company_id) VALUES (1, 'Your Company', 'en_US', 1);
insert into ir_model_data (name,module,model,noupdate,res_id) VALUES ('main_partner','base','res.partner',true,1);
-- Compatibility purpose, to remove V6.0
insert into ir_model_data (name,module,model,noupdate,res_id) values ('user_admin','base','res.users',True,1);
insert into res_currency (id, name) VALUES (1, 'EUR');
insert into ir_model_data (name,module,model,noupdate,res_id) VALUES ('EUR','base','res.currency',true,1);
insert into res_company (id, name, partner_id, currency_id) VALUES (1, 'Your Company', 1, 1);
insert into ir_model_data (name,module,model,noupdate,res_id) VALUES ('main_company','base','res.company',true,1);
select setval('res_company_id_seq', 2);
select setval('res_users_id_seq', 2);
select setval('res_partner_id_seq', 2);
select setval('res_currency_id_seq', 2);

View File

@ -32,6 +32,7 @@
<record id="main_partner" model="res.partner" context="{'default_is_company': True}">
<field name="name">Your Company</field>
<field name="company_id" eval="None"/>
<field name="image" eval="False"/>
<field name="customer" eval="False"/>
<field name="is_company" eval="True"/>
<field name="street"></field>
@ -61,7 +62,7 @@
<record id="main_company" model="res.company">
<field name="name">Your Company</field>
<field name="partner_id" ref="main_partner"/>
<field name="rml_header1">Your Company Slogan</field>
<field name="rml_header1">Your Company Tagline</field>
<field name="currency_id" ref="base.EUR"/>
</record>
@ -77,7 +78,8 @@
<field name="company_id" ref="main_company"/>
<field name="company_ids" eval="[(4, ref('main_company'))]"/>
<field name="menu_id" ref="action_menu_admin"/>
<field name="signature">Administrator</field>
<field name="signature">--
Administrator</field>
</record>
<record id="main_partner" model="res.partner">
@ -87,6 +89,13 @@
<record id="EUR" model="res.currency">
<field name="company_id" ref="main_company"/>
</record>
<record id="ir_mail_server_localhost0" model="ir.mail_server">
<field name="name">localhost</field>
<field name="smtp_host">localhost</field>
<field eval="25" name="smtp_port"/>
<field eval="10" name="sequence"/>
</record>
</data>
</openerp>

View File

@ -7,17 +7,236 @@
<field name="customer" eval="False"/>
<field name="email">demo@example.com</field>
</record>
<record id="main_partner" model="res.partner">
<field name="image">iVBORw0KGgoAAAANSUhEUgAAALQAAAAuCAYAAACBMDMXAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A
/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDCAo7GWN31l0AAA1fSURBVHja
7Zx5dFXFHcc/eQk7KBiUTVGRRezA8ahYamgRFbWAcmyPe+uGSrW1FrFqF9u61bZWm1Kx1lgVpHVp
3ShVVBTcBYSyDHHBulEUhVRBRJJA0j/m95rJZOa++zYS2vs95xLevLkzc+d+72++v99v7oMECRIk
SJAgQYIECRIkSJAgQYIECQqB9skUFA4luZ6ooRzoA/QGPgWqlfn7/4aBwJHAEUA/oANwA3C/Vaen
/N3gnPs14ErgaGB9QscdSGgNewHj5TgC6Oyp9h6wylTnUQULdsI52U2Oj4GaiHoVwC3AcM93a4DB
QHfgAeAwoBFYAVwjZe2AamA/ma8jA6SeAowDtgH18neb9Rmg1DrK5Ggn1r+dlH8ObAE+A24D5su5
/YCZVtvu30an/XQf7eXYJNe7BlhMvHs+DPhNRJ8pGbd9Lem/24C10t/bMpebsrHEAzXco6FBQ6Mc
72qYoeEaDZdoqNKwSMMWq06jhuc1jNxJiHww8ILcwEaZuHnANz0P/qFAg1XXd9wKvB/4bgZwvnxf
AawTsu/uGddlwKtCxsYCHZOs9vsBS4APCtT2QuCYGIReBnxUgP4+Aa4DukRaaG2Wzl8D35KnA7Eo
l4v1bfCcs4c87fYF1QMXK/h9GybzaOBpsQw+PAucC6yWzw8CJ+TZZwPwE7kZ+wBzgVpZ/WoCq+kM
ecBcrBDS18pRJ39LgF5yfBHoKvUnAH/3tHMg8A9P+RZgmvRRAwwAFHAG0NFTf5vM6Ysx5uFY4DFP
+QYxCq8DG4Eh0uaEQDuzAnNjiKnhRcfaPqShWwyLXqLhaufcRg3faKNk3gV4N4Yl+Fz0bgdgeYz6
f5KlfVtEnanWOMqFMEuBHoGxTgq0c3FMKfWW1D84ot7HnvbXBOr2F0PgG9O/gE4xxtUhcP7iQP3j
ga2Bc071EXKASAqbjPN12Hr52ijV8KbTxgbtX1JbGzOyXOLWigXMVCf98A8RvfhhoF6ZNZZ9RH4s
Bnb1jHVCHoQGeFzq94uo81oWhEZkUkg6fCnmuD7JgtCI0+3r7+6UQ8TOwEPy5KWxHjjdJzFCULAd
+IVTXA5UtjEydw8uU2HUyTLow/sit74rcqKv1J0iJJoo0Y8tUr8vcJR1/jtC2qHyoLnINxKyVm78
RxF1su1jfcR9PTiLNrLBTYHy4a7VvcPjtV+vzI3KFjNFx9k4TRuHqq1gRIZIT4M4TDeKZu4D7CtO
zUjReD8SP2M8cJI4jA8A35eyPpaunA2cjPE1TgWeEX1o4xXgFOA44ETnu9o8r3eatFkfUSeXPpYH
yrvFPD/bPj/AHyIuL7Os8wSZbByHblYuM6egTpsw3iAPiRa1EULv7SHwCglpLRBn8BPPeZ2B74im
rXO+SwFnAXfJ3E0HrnCs4mfAvcB9gXHNEX29scDXu0yOQmNdlkQvBNYAB7j92frtp76JVfktc+94
CD00jmMp9d5ULQnj1h0EbFXROi+EOw+Exy6FASWwsRLeWGwcjkiUwujr4Y5x0Khafv2cRBNKgc+v
g6pnYfDj/mW+MaKbtibPouDTyltltSkWenrKlpZZ1vkQT4U78uz0XU/Z/hHkbC9L9cXibMwEzvTU
GwX8QEJR5VI2WZmoQhyntauE4c6Wp7wM4E7zUFyojIWMM747gXM89Z4GLpIQZ++JUHsjjFHwUisR
bprM0+lFav9wT9k1GbR6Pugmss3FC2kLfWZgGZmbZ8c+bTQ0QJZREuayv+/qIeL1wLc92ncSGQit
Tabph8D3MIH4hRJ9SHv9ewH3aRimTIgr0/jae/oYIpJhoBOaGkfrEfqrGXRzPhiGSd03I5ZEIoqF
SZ6yB4C5KW2s01hfBWUcmXzQ31NW5hAgpY1jtcBD9lVWvaHAStGuPhkyTJtlPkTmgZhA/8/EcgxR
8GXR0fc7+nhCzPEtcvoYLaQd6BnCm61E5nJgT2JIqRywPyabajt/DwqfivUA7Ss+iRu9OT9NrsPw
xzzfKEDn/QMeapoAe4jjNFb6G+wjtDb7HeYBm2WJv18mzrYMnYRIr3vIPAIjA7piQopHK5FDCrZr
uFsiFM30mTO+1R5/YKHVxxlAlTgr9Z4lcVkRSXuO3Mc6uT77OoZhsnm1Beqri0RuTpSVLn2dS0Rm
zM7gG2SLMZjsZAlmm8BVjn5+DRN6/Xea0KG9Fu8VIYrQjNDypJViUq4rMOnO3azvq7WRA08Joc9O
x8M1POFZ6uo9ZO4LPGzJl4dVS23fxflcHRhfDU1ZvLo0SbWJOU/FkPovMsF3We3VWW0WA8Pxb5LC
GUO+eASTqXOxUqJXjUW4tmnG7njl7M8x+Y46e/nvlYVDFxuSJu8eiHzYkZXNymQSu9A85VsvVnu2
jOU8J7nzsaftDZ6yKgyp0/idp44tudbT5BTa49vFGd8yBbXaWKpLxOovtOSNjZdV8ZZggEdlBdps
WeISWfEmilRqV4B+7gkQepgs+X8owrVdIM57bwljLpdjCZ4IXFnAW8yb0AG5AcayIsu9HRwf7Dh6
K4DTRDON9ITvXD1bp5xthLLl9VjbkiiTzLDrfEUmDEwGb7IyxHDH58Y8F2mjTacBxyhLfnjCWPOK
rJOfAH4b+G6WWNCOBejnXrknx3m+uwGzyei9Al/b83LEQgr//orNSjRJHjgksOw9GeFguJLnWmB8
YCwHxHC6zqL5HpQqh8xjxTtOiV4foUzq3wfl8eTvBipVcy2domU2tNiEjsIqTKa3QwEt5qZAKK2K
VkYqECssxFN2lqdsftr6xSD0OGCmatqymSn896RD1hLL8v63/3RoTcPNEpbsJuG4Q1W0zrUJvV10
dZknPKUcr/9Tojfa7AgspHBvxKzF7NH24Wg8cfkdTehXPeWleernAZgQlm9ZCmGI83kL8MtA+50x
O9O8UkYwWuSK7USM1Sb8ls7mnQj0VEZmbMlwWV+wVzDx8M/3bNpy5caCAoQ/88XX8Sc/csVtONLN
wk1E7+YrKsoChO5fAOtc4rHOT0Wc40qI6cq/jwJMksNuf6Nngke4MkrCTT8GXlLNw1uZHtAUcJBV
tKtES3xzV+F8for/PTQC54mf42rzXcU5nNBaFtq3zHbKde+y3Hw389iASVVHRURcQs+O6MaVEtOU
2fBjw400PK3gMgXPZ0NmwaE0DycSWj0w8eC2op996IlxlvPFakySyofxmBBmqxD6nwGRPyiP5c21
8Jc5UQAXIx2Z8yGBjS3ahM5OcCxvZYzx1+QxT+Ocz0sVvOwZWy9MEiiNTcrKdrYRzCHeq1FxcCPm
DRsfKmnaOrvjCC3Wymc9L8rBOvel5buDdylz4VEY5Xyeq8JB+tMcj/3SQBRkkOfhzTT+kpiEnh+o
V+GJMLQldMVsuo96uDvGLAPjG0zC7yP0IP57pL72O+VEaPl7Ky0tzkk6xlZPiwydMO/RlVvF9wGT
Y5zuEuHZiLq2F12pPMF8IWafDKR0zxkLLNWOsylW9yCn+nMx5YaWf8o0XKmbz00uKMnz/FHiN9Vk
kCQudoswCMsinP2JYoDiyCAXvXImtHjq59E8m5XC/DzBHjHI3AsTPTjcchquAk6NsZ+5FLMN1MaL
gbqThVwNmJTnVF89se5vO8V76pYrARqGaxO+e0wcSzfbeKxDpEbCgX73wewtLwdrebB750nIXM/v
iElcnRJDfvUM8KRHxDlXE977c7MTIXLRDv9eonJyiLaVWSTQ2ujf6ZbTUAEs18bJe9KVAaJnz8W8
M5e2iK+KZp4TcwwH4mwTBa7ScJOVSu6CeWVpOmZb5xnKJDai8JzHMZyrTcjpbem3Qm7048DwQBza
tezVykMIbUjjWvLj5JgBTFH+dH02ODlQfqlYwjrrqBcrtzfGKJVE+BPt5f6N9ji/aVyAyRSuxbwB
b2Or8OAZzyrSQxzjKcDfaHLeO2Ik6vERq9GFovk/JHNY1b+ECXmuxOxPsPP/myRMsxITlRiE2RDT
yfJ6rwVmZfNCrTYvlIbStpsxKfj9ZAKqgEsikjN2u70lghNlWaqBqSqw71u21q6n+Z6UW5W5uW7d
AzyaeQ0mVp3vvvI9MSns0QXS0tdhwpfI3Ga7tXU8Zv+Ii1vwzI2F20UJVJBFOltwWxz5WuZZrj8D
rtDGqpyE0dFDxZKNshy4GiH4HGC2Mv/PVdfZqBWLUYJJoJQCfwX+rPw/SEJAdqzTxgGqFNnQXuTC
aszGlnnAjAwhvH3lvGWy8lRjUuU+pH9T4yB56B8BflWg3/vrLku6pumHZNI/pZD+2az0z365Rz1N
P0CTPh622v4U+KPUSx91lvz0tbk2MM7LZTz1YsW3Csc6ypGOdH1k9Vnn9G33WWb9/6WcLHSExUth
HKZtwDpVmO2IaDM5fZ3oyu0iez6IY41j9FEqS+8Glc3voGXfTwrYXZklMkEroKQ1O9fGAr7lRgpa
8d27BDs5Uq3cvxsV2E5x3+xIkBC6qHD18yrV0oNOkGCntdBLkluSYKcktGTN3ID7K8ktSbCzWugx
Hqc0IXSCnZbQRzqf68k9lp0gQasT+iiPQ7g1uSUJ8kFZK+nn/ph9Fo2Y1PZKmv96UYIEOeE/+J4k
BZrmED0AAAAASUVORK5CYII=
</field>
</record>
<record id="user_demo" model="res.users">
<field name="partner_id" ref="base.partner_demo"/>
<field name="login">demo</field>
<field name="password">demo</field>
<field name="signature">Mr Demo</field>
<field name="signature">--
Mr Demo</field>
<field name="company_id" ref="main_company"/>
<field name="groups_id" eval="[(6,0,[ref('base.group_user')])]"/>
<field name="groups_id" eval="[(6,0,[ref('base.group_user'), ref('base.group_partner_manager')])]"/>
<field name="image">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
gk//2Q==</field>
</record>
<record model="res.partner" id="base.partner_root">
<field name="email">admin@example.com</field>
<field name="tz">Europe/Brussels</field>
<field name="image">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
kALR5oiAU7jnCuj0RFIHQbIiKAf/2Q==</field>
</record>
<!-- new rate for demo transactions in multi currency -->
@ -26,5 +245,6 @@
<field name="currency_id" ref="USD"/>
<field eval="time.strftime('%Y-06-06')" name="name"/>
</record>
</data>
</openerp>

View File

@ -510,14 +510,6 @@
<field name="currency_id" ref="CRC"/>
<field eval="time.strftime('%Y-01-01')" name="name"/>
</record>
<record id="ir_mail_server_localhost0" model="ir.mail_server">
<field name="name">localhost</field>
<field name="smtp_host">localhost</field>
<field eval="25" name="smtp_port"/>
<field eval="10" name="sequence"/>
</record>
<record id="MUR" model="res.currency">
<field name="name">MUR</field>
<field name="symbol">Rs</field>
@ -1977,6 +1969,7 @@
<field name="symbol">£</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field name="position">before</field>
<field name="company_id" ref="main_company"/>
</record>
<record id="rateGBP" model="res.currency.rate">

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

15312
openerp/addons/base/i18n/hi.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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