odoo系统的web服务器,Web Service API

Odoo is usually extended internally via modules, but many of its features and

all of its data are also available from the outside for external analysis or

integration with various tools. Part of the Model Reference API is

easily available over XML-RPC and accessible from a variety of languages.Connection

import xmlrpclib

info = xmlrpclib.ServerProxy('https://demo.odoo.com/start').start()

url, db, username, password = \

info['host'], info['database'], info['user'], info['password']

common = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(url))

uid = common.authenticate(db, username, password, {})

models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))

require "xmlrpc/client"

info = XMLRPC::Client.new2('https://demo.odoo.com/start').call('start')

url, db, username, password = \

info['host'], info['database'], info['user'], info['password']

common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common")

uid = common.call('authenticate', db, username, password, {})

models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy

require_once('ripcord.php');

$info = ripcord::client('https://demo.odoo.com/start')->start();

list($url, $db, $username, $password) =

array($info['host'], $info['database'], $info['user'], $info['password']);

$common = ripcord::client("$url/xmlrpc/2/common");

$uid = $common->authenticate($db, $username, $password, array());

$models = ripcord::client("$url/xmlrpc/2/object");

final XmlRpcClient client = new XmlRpcClient();

final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl();

start_config.setServerURL(new URL("https://demo.odoo.com/start"));

final Map info = (Map)client.execute(

start_config, "start", emptyList());

final String url = info.get("host"),

db = info.get("database"),

username = info.get("user"),

password = info.get("password");

final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl();

common_config.setServerURL(new URL(String.format("%s/xmlrpc/2/common", url)));

int uid = (int)client.execute(

common_config, "authenticate", Arrays.asList(

db, username, password, emptyMap()));

final XmlRpcClient models = new XmlRpcClient() {{

setConfig(new XmlRpcClientConfigImpl() {{

setServerURL(new URL(String.format("%s/xmlrpc/2/object", url)));

}});

}};Configuration

If you already have an Odoo server installed, you can just use its

parameters

Warning

For Odoo Online instances (.odoo.com), users are created without a

local password (as a person you are logged in via the Odoo Online

authentication system, not by the instance itself). To use XML-RPC on Odoo

Online instances, you will need to set a password on the user account you

want to use:Log in your instance with an administrator account

Go to Settings ‣ Users ‣ Users

Click on the user you want to use for XML-RPC access

Click the Change Password button

Set a New Password value then click

Change Password.

The server url is the instance's domain (e.g.

https://mycompany.odoo.com), the database name is the name of the

instance (e.g. mycompany). The username is the configured user's login

as shown by the Change Password screen.

Python

Ruby

PHP

Java

url =

db =

username = 'admin'

password =

url =

db =

username = "admin"

password =

$url = ;

$db = ;

$username = "admin";

$password = ;

final String url = ,

db = ,

username = "admin",

password = ;demo

To make exploration simpler, you can also ask https://demo.odoo.com for a test

database:

Python

Ruby

PHP

Java

import xmlrpclib

info = xmlrpclib.ServerProxy('https://demo.odoo.com/start').start()

url, db, username, password = \

info['host'], info['database'], info['user'], info['password']

require "xmlrpc/client"

info = XMLRPC::Client.new2('https://demo.odoo.com/start').call('start')

url, db, username, password = \

info['host'], info['database'], info['user'], info['password']

require_once('ripcord.php');

$info = ripcord::client('https://demo.odoo.com/start')->start();

list($url, $db, $username, $password) =

array($info['host'], $info['database'], $info['user'], $info['password']);

Note

These examples use the Ripcord

library, which provides a simple XML-RPC API. Ripcord requires that

XML-RPC support be enabled in your PHP

installation.

Since calls are performed over

HTTPS, it also requires that

the OpenSSL extension be enabled.

final XmlRpcClient client = new XmlRpcClient();

final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl();

start_config.setServerURL(new URL("https://demo.odoo.com/start"));

final Map info = (Map)client.execute(

start_config, "start", emptyList());

final String url = info.get("host"),

db = info.get("database"),

username = info.get("user"),

password = info.get("password");

Note

These examples use the Apache XML-RPC library

The examples do not include imports as these imports couldn't be

pasted in the code.Logging in

Odoo requires users of the API to be authenticated before they can query most

data.

The xmlrpc/2/common endpoint provides meta-calls which don't require

authentication, such as the authentication itself or fetching version

information. To verify if the connection information is correct before trying

to authenticate, the simplest call is to ask for the server's version. The

authentication itself is done through the authenticate function and

returns a user identifier (uid) used in authenticated calls instead of

the login.

Python

Ruby

PHP

Java

common = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(url))

common.version()

common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common")

common.call('version')

$common = ripcord::client("$url/xmlrpc/2/common");

$common->version();

final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl();

common_config.setServerURL(

new URL(String.format("%s/xmlrpc/2/common", url)));

client.execute(common_config, "version", emptyList());

{

"server_version": "8.0",

"server_version_info": [8, 0, 0, "final", 0],

"server_serie": "8.0",

"protocol_version": 1,

}

Python

Ruby

PHP

Java

uid = common.authenticate(db, username, password, {})

uid = common.call('authenticate', db, username, password, {})

$uid = $common->authenticate($db, $username, $password, array());

int uid = (int)client.execute(

common_config, "authenticate", asList(

db, username, password, emptyMap()));Calling methods

The second endpoint is xmlrpc/2/object, is used to call methods of odoo

models via the execute_kw RPC function.

Each call to execute_kw takes the following parameters:the database to use, a string

the user id (retrieved through authenticate), an integer

the user's password, a string

the model name, a string

the method name, a string

an array/list of parameters passed by position

a mapping/dict of parameters to pass by keyword (optional)

For instance to see if we can read the res.partner model we can call

check_access_rights with operation passed by position and

raise_exception passed by keyword (in order to get a true/false result

rather than true/error):

Python

Ruby

PHP

Java

models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))

models.execute_kw(db, uid, password,

'res.partner', 'check_access_rights',

['read'], {'raise_exception': False})

models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy

models.execute_kw(db, uid, password,

'res.partner', 'check_access_rights',

['read'], {raise_exception: false})

$models = ripcord::client("$url/xmlrpc/2/object");

$models->execute_kw($db, $uid, $password,

'res.partner', 'check_access_rights',

array('read'), array('raise_exception' => false));

final XmlRpcClient models = new XmlRpcClient() {{

setConfig(new XmlRpcClientConfigImpl() {{

setServerURL(new URL(String.format("%s/xmlrpc/2/object", url)));

}});

}};

models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "check_access_rights",

asList("read"),

new HashMap() {{ put("raise_exception", false); }}

));

trueList records

Records can be listed and filtered via search().

search() takes a mandatory

domain filter (possibly empty), and returns the

database identifiers of all records matching the filter. To list customer

companies for instance:

Python

Ruby

PHP

Java

models.execute_kw(db, uid, password,

'res.partner', 'search',

[[['is_company', '=', True], ['customer', '=', True]]])

models.execute_kw(db, uid, password,

'res.partner', 'search',

[[['is_company', '=', true], ['customer', '=', true]]])

$models->execute_kw($db, $uid, $password,

'res.partner', 'search', array(

array(array('is_company', '=', true),

array('customer', '=', true))));

asList((Object[])models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "search",

asList(asList(

asList("is_company", "=", true),

asList("customer", "=", true)))

)));

[7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74]Pagination

By default a search will return the ids of all records matching the

condition, which may be a huge number. offset and limit parameters are

available to only retrieve a subset of all matched records.

Python

Ruby

PHP

Java

models.execute_kw(db, uid, password,

'res.partner', 'search',

[[['is_company', '=', True], ['customer', '=', True]]],

{'offset': 10, 'limit': 5})

models.execute_kw(db, uid, password,

'res.partner', 'search',

[[['is_company', '=', true], ['customer', '=', true]]],

{offset: 10, limit: 5})

$models->execute_kw($db, $uid, $password,

'res.partner', 'search',

array(array(array('is_company', '=', true),

array('customer', '=', true))),

array('offset'=>10, 'limit'=>5));

asList((Object[])models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "search",

asList(asList(

asList("is_company", "=", true),

asList("customer", "=", true))),

new HashMap() {{ put("offset", 10); put("limit", 5); }}

)));

[13, 20, 30, 22, 29]Count records

Rather than retrieve a possibly gigantic list of records and count them,

search_count() can be used to retrieve

only the number of records matching the query. It takes the same

domain filter as

search() and no other parameter.

Python

Ruby

PHP

Java

models.execute_kw(db, uid, password,

'res.partner', 'search_count',

[[['is_company', '=', True], ['customer', '=', True]]])

models.execute_kw(db, uid, password,

'res.partner', 'search_count',

[[['is_company', '=', true], ['customer', '=', true]]])

$models->execute_kw($db, $uid, $password,

'res.partner', 'search_count',

array(array(array('is_company', '=', true),

array('customer', '=', true))));

(Integer)models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "search_count",

asList(asList(

asList("is_company", "=", true),

asList("customer", "=", true)))

));

19

Warning

calling search then search_count (or the other way around) may not

yield coherent results if other users are using the server: stored data

could have changed between the callsRead records

Record data is accessible via the read() method,

which takes a list of ids (as returned by

search()) and optionally a list of fields to

fetch. By default, it will fetch all the fields the current user can read,

which tends to be a huge amount.

Python

Ruby

PHP

Java

ids = models.execute_kw(db, uid, password,

'res.partner', 'search',

[[['is_company', '=', True], ['customer', '=', True]]],

{'limit': 1})

[record] = models.execute_kw(db, uid, password,

'res.partner', 'read', [ids])

# count the number of fields fetched by default

len(record)

ids = models.execute_kw(db, uid, password,

'res.partner', 'search',

[[['is_company', '=', true], ['customer', '=', true]]],

{limit: 1})

record = models.execute_kw(db, uid, password,

'res.partner', 'read', [ids]).first

# count the number of fields fetched by default

record.length

$ids = $models->execute_kw($db, $uid, $password,

'res.partner', 'search',

array(array(array('is_company', '=', true),

array('customer', '=', true))),

array('limit'=>1));

$records = $models->execute_kw($db, $uid, $password,

'res.partner', 'read', array($ids));

// count the number of fields fetched by default

count($records[0]);

final List ids = asList((Object[])models.execute(

"execute_kw", asList(

db, uid, password,

"res.partner", "search",

asList(asList(

asList("is_company", "=", true),

asList("customer", "=", true))),

new HashMap() {{ put("limit", 1); }})));

final Map record = (Map)((Object[])models.execute(

"execute_kw", asList(

db, uid, password,

"res.partner", "read",

asList(ids)

)

))[0];

// count the number of fields fetched by default

record.size();

121

Conversedly, picking only three fields deemed interesting.

Python

Ruby

PHP

Java

models.execute_kw(db, uid, password,

'res.partner', 'read',

[ids], {'fields': ['name', 'country_id', 'comment']})

models.execute_kw(db, uid, password,

'res.partner', 'read',

[ids], {fields: %w(name country_id comment)})

$models->execute_kw($db, $uid, $password,

'res.partner', 'read',

array($ids),

array('fields'=>array('name', 'country_id', 'comment')));

asList((Object[])models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "read",

asList(ids),

new HashMap() {{

put("fields", asList("name", "country_id", "comment"));

}}

)));

[{"comment": false, "country_id": [21, "Belgium"], "id": 7, "name": "Agrolait"}]

Note

even if the id field is not requested, it is always returnedListing record fields

fields_get() can be used to inspect

a model's fields and check which ones seem to be of interest.

Because it returns a large amount of meta-information (it is also used by client

programs) it should be filtered before printing, the most interesting items

for a human user are string (the field's label), help (a help text if

available) and type (to know which values to expect, or to send when

updating a record):

Python

Ruby

PHP

Java

models.execute_kw(

db, uid, password, 'res.partner', 'fields_get',

[], {'attributes': ['string', 'help', 'type']})

models.execute_kw(

db, uid, password, 'res.partner', 'fields_get',

[], {attributes: %w(string help type)})

$models->execute_kw($db, $uid, $password,

'res.partner', 'fields_get',

array(), array('attributes' => array('string', 'help', 'type')));

(Map>)models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "fields_get",

emptyList(),

new HashMap() {{

put("attributes", asList("string", "help", "type"));

}}

));

{

"ean13": {

"type": "char",

"help": "BarCode",

"string": "EAN13"

},

"property_account_position": {

"type": "many2one",

"help": "The fiscal position will determine taxes and accounts used for the partner.",

"string": "Fiscal Position"

},

"signup_valid": {

"type": "boolean",

"help": "",

"string": "Signup Token is Valid"

},

"date_localization": {

"type": "date",

"help": "",

"string": "Geo Localization Date"

},

"ref_companies": {

"type": "one2many",

"help": "",

"string": "Companies that refers to partner"

},

"sale_order_count": {

"type": "integer",

"help": "",

"string": "# of Sales Order"

},

"purchase_order_count": {

"type": "integer",

"help": "",

"string": "# of Purchase Order"

},Search and read

Because it is a very common task, Odoo provides a

search_read() shortcut which as its name notes is

equivalent to a search() followed by a

read(), but avoids having to perform two requests

and keep ids around.

Its arguments are similar to search()'s, but it

can also take a list of fields (like read(),

if that list is not provided it will fetch all fields of matched records):

Python

Ruby

PHP

Java

models.execute_kw(db, uid, password,

'res.partner', 'search_read',

[[['is_company', '=', True], ['customer', '=', True]]],

{'fields': ['name', 'country_id', 'comment'], 'limit': 5})

models.execute_kw(db, uid, password,

'res.partner', 'search_read',

[[['is_company', '=', true], ['customer', '=', true]]],

{fields: %w(name country_id comment), limit: 5})

$models->execute_kw($db, $uid, $password,

'res.partner', 'search_read',

array(array(array('is_company', '=', true),

array('customer', '=', true))),

array('fields'=>array('name', 'country_id', 'comment'), 'limit'=>5));

asList((Object[])models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "search_read",

asList(asList(

asList("is_company", "=", true),

asList("customer", "=", true))),

new HashMap() {{

put("fields", asList("name", "country_id", "comment"));

put("limit", 5);

}}

)));

[

{

"comment": false,

"country_id": [ 21, "Belgium" ],

"id": 7,

"name": "Agrolait"

},

{

"comment": false,

"country_id": [ 76, "France" ],

"id": 18,

"name": "Axelor"

},

{

"comment": false,

"country_id": [ 233, "United Kingdom" ],

"id": 12,

"name": "Bank Wealthy and sons"

},

{

"comment": false,

"country_id": [ 105, "India" ],

"id": 14,

"name": "Best Designers"

},

{

"comment": false,

"country_id": [ 76, "France" ],

"id": 17,

"name": "Camptocamp"

}

]Create records

Records of a model are created using create(). The

method will create a single record and return its database identifier.

create() takes a mapping of fields to values, used

to initialize the record. For any field which has a default value and is not

set through the mapping argument, the default value will be used.

Python

Ruby

PHP

Java

id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{

'name': "New Partner",

}])

id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{

name: "New Partner",

}])

$id = $models->execute_kw($db, $uid, $password,

'res.partner', 'create',

array(array('name'=>"New Partner")));

final Integer id = (Integer)models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "create",

asList(new HashMap() {{ put("name", "New Partner"); }})

));

78

Warning

while most value types are what would be expected (integer for

Integer, string for Char

or Text),Date, Datetime and

Binary fields use string valuesUpdate records

Records can be updated using write(), it takes

a list of records to update and a mapping of updated fields to values similar

to create().

Multiple records can be updated simultanously, but they will all get the same

values for the fields being set. It is not currently possible to perform

"computed" updates (where the value being set depends on an existing value of

a record).

Python

Ruby

PHP

Java

models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], {

'name': "Newer partner"

}])

# get record name after having changed it

models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]])

models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], {

name: "Newer partner"

}])

# get record name after having changed it

models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]])

$models->execute_kw($db, $uid, $password, 'res.partner', 'write',

array(array($id), array('name'=>"Newer partner")));

// get record name after having changed it

$models->execute_kw($db, $uid, $password,

'res.partner', 'name_get', array(array($id)));

models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "write",

asList(

asList(id),

new HashMap() {{ put("name", "Newer Partner"); }}

)

));

// get record name after having changed it

asList((Object[])models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "name_get",

asList(asList(id))

)));

[[78, "Newer partner"]]Delete records

Records can be deleted in bulk by providing their ids to

unlink().

Python

Ruby

PHP

Java

models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]])

# check if the deleted record is still in the database

models.execute_kw(db, uid, password,

'res.partner', 'search', [[['id', '=', id]]])

models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]])

# check if the deleted record is still in the database

models.execute_kw(db, uid, password,

'res.partner', 'search', [[['id', '=', id]]])

$models->execute_kw($db, $uid, $password,

'res.partner', 'unlink',

array(array($id)));

// check if the deleted record is still in the database

$models->execute_kw($db, $uid, $password,

'res.partner', 'search',

array(array(array('id', '=', $id))));

models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "unlink",

asList(asList(id))));

// check if the deleted record is still in the database

asList((Object[])models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "search",

asList(asList(asList("id", "=", 78)))

)));

[]Inspection and introspection

While we previously used fields_get() to query a

model and have been using an arbitrary model from the start, Odoo stores

most model metadata inside a few meta-models which allow both querying the

system and altering models and fields (with some limitations) on the fly over

XML-RPC.ir.model

Provides information about Odoo models via its various fieldsnamea human-readable description of the modelmodelthe name of each model in the systemstatewhether the model was generated in Python code (base) or by creating

an ir.model record (manual)field_idlist of the model's fields through a One2many to

ir.model.fieldsview_idsOne2many to the Views defined

for the modelaccess_idsOne2many relation to the

Access Control set on the model

ir.model can be used toquery the system for installed models (as a precondition to operations

on the model or to explore the system's content)

get information about a specific model (generally by listing the fields

associated with it)

create new models dynamically over RPC

Warning"custom" model names must start with x_

the state must be provided and manual, otherwise the model will

not be loaded

it is not possible to add new methods to a custom model, only fields

a custom model will initially contain only the "built-in" fields available

on all models:

Python

PHP

Ruby

Java

models.execute_kw(db, uid, password, 'ir.model', 'create', [{

'name': "Custom Model",

'model': "x_custom_model",

'state': 'manual',

}])

models.execute_kw(

db, uid, password, 'x_custom_model', 'fields_get',

[], {'attributes': ['string', 'help', 'type']})

$models->execute_kw(

$db, $uid, $password,

'ir.model', 'create', array(array(

'name' => "Custom Model",

'model' => 'x_custom_model',

'state' => 'manual'

))

);

$models->execute_kw(

$db, $uid, $password,

'x_custom_model', 'fields_get',

array(),

array('attributes' => array('string', 'help', 'type'))

);

models.execute_kw(

db, uid, password,

'ir.model', 'create', [{

name: "Custom Model",

model: 'x_custom_model',

state: 'manual'

}])

fields = models.execute_kw(

db, uid, password, 'x_custom_model', 'fields_get',

[], {attributes: %w(string help type)})

models.execute(

"execute_kw", asList(

db, uid, password,

"ir.model", "create",

asList(new HashMap() {{

put("name", "Custom Model");

put("model", "x_custom_model");

put("state", "manual");

}})

));

final Object fields = models.execute(

"execute_kw", asList(

db, uid, password,

"x_custom_model", "fields_get",

emptyList(),

new HashMap () {{

put("attributes", asList(

"string",

"help",

"type"));

}}

));

{

"create_uid": {

"type": "many2one",

"string": "Created by"

},

"create_date": {

"type": "datetime",

"string": "Created on"

},

"__last_update": {

"type": "datetime",

"string": "Last Modified on"

},

"write_uid": {

"type": "many2one",

"string": "Last Updated by"

},

"write_date": {

"type": "datetime",

"string": "Last Updated on"

},

"display_name": {

"type": "char",

"string": "Display Name"

},

"id": {

"type": "integer",

"string": "Id"

}

}ir.model.fields

Provides information about the fields of Odoo models and allows adding

custom fields without using Python codemodel_idMany2one to

ir.model to which the field belongsnamethe field's technical name (used in read or write)field_descriptionthe field's user-readable label (e.g. string in fields_get)ttypethe type of field to createstatewhether the field was created via Python code (base) or via

ir.model.fields (manual)required, readonly, translateenables the corresponding flag on the fieldgroupsselection, size, on_delete, relation, relation_field, domaintype-specific properties and customizations, see the fields

documentation for details

Like custom models, only new fields created with state="manual" are

activated as actual fields on the model.

Warning

computed fields can not be added via ir.model.fields, some

field meta-information (defaults, onchange) can not be set either

Python

PHP

Ruby

Java

id = models.execute_kw(db, uid, password, 'ir.model', 'create', [{

'name': "Custom Model",

'model': "x_custom",

'state': 'manual',

}])

models.execute_kw(

db, uid, password,

'ir.model.fields', 'create', [{

'model_id': id,

'name': 'x_name',

'ttype': 'char',

'state': 'manual',

'required': True,

}])

record_id = models.execute_kw(

db, uid, password,

'x_custom', 'create', [{

'x_name': "test record",

}])

models.execute_kw(db, uid, password, 'x_custom', 'read', [[record_id]])

$id = $models->execute_kw(

$db, $uid, $password,

'ir.model', 'create', array(array(

'name' => "Custom Model",

'model' => 'x_custom',

'state' => 'manual'

))

);

$models->execute_kw(

$db, $uid, $password,

'ir.model.fields', 'create', array(array(

'model_id' => $id,

'name' => 'x_name',

'ttype' => 'char',

'state' => 'manual',

'required' => true

))

);

$record_id = $models->execute_kw(

$db, $uid, $password,

'x_custom', 'create', array(array(

'x_name' => "test record"

))

);

$models->execute_kw(

$db, $uid, $password,

'x_custom', 'read',

array(array($record_id)));

id = models.execute_kw(

db, uid, password,

'ir.model', 'create', [{

name: "Custom Model",

model: "x_custom",

state: 'manual'

}])

models.execute_kw(

db, uid, password,

'ir.model.fields', 'create', [{

model_id: id,

name: "x_name",

ttype: "char",

state: "manual",

required: true

}])

record_id = models.execute_kw(

db, uid, password,

'x_custom', 'create', [{

x_name: "test record"

}])

models.execute_kw(

db, uid, password,

'x_custom', 'read', [[record_id]])

final Integer id = (Integer)models.execute(

"execute_kw", asList(

db, uid, password,

"ir.model", "create",

asList(new HashMap() {{

put("name", "Custom Model");

put("model", "x_custom");

put("state", "manual");

}})

));

models.execute(

"execute_kw", asList(

db, uid, password,

"ir.model.fields", "create",

asList(new HashMap() {{

put("model_id", id);

put("name", "x_name");

put("ttype", "char");

put("state", "manual");

put("required", true);

}})

));

final Integer record_id = (Integer)models.execute(

"execute_kw", asList(

db, uid, password,

"x_custom", "create",

asList(new HashMap() {{

put("x_name", "test record");

}})

));

client.execute(

"execute_kw", asList(

db, uid, password,

"x_custom", "read",

asList(asList(record_id))

));

[

{

"create_uid": [1, "Administrator"],

"x_name": "test record",

"__last_update": "2014-11-12 16:32:13",

"write_uid": [1, "Administrator"],

"write_date": "2014-11-12 16:32:13",

"create_date": "2014-11-12 16:32:13",

"id": 1,

"display_name": "test record"

}

]Workflow manipulations

Workflows can be moved along by sending them signals.

Instead of using the top-level execute_kw, signals are sent using

exec_workflow.

Signals are sent to a specific record, and possibly trigger a transition on

the workflow instance associated with the record.

Warning

this example needs account module installed

Python

PHP

Ruby

Java

client = models.execute_kw(

db, uid, password,

'res.partner', 'search_read',

[[('customer', '=', True)]],

{'limit': 1, 'fields': [

'property_account_receivable',

'property_payment_term',

'property_account_position']

})[0]

invoice_id = models.execute_kw(

db, uid, password,

'account.invoice', 'create', [{

'partner_id': client['id'],

'account_id': client['property_account_receivable'][0],

'invoice_line': [(0, False, {'name': "AAA"})]

}])

models.exec_workflow(

db, uid, password, 'account.invoice', 'invoice_open', invoice_id)

$client = $models->execute_kw(

$db, $uid, $password,

'res.partner', 'search_read',

array(array(array('customer', '=', true))),

array(

'limit' => 1,

'fields' => array(

'property_account_receivable',

'property_payment_term',

'property_account_position'

)))[0];

$invoice_id = $models->execute_kw(

$db, $uid, $password,

'account.invoice', 'create', array(array(

'partner_id' => $client['id'],

'account_id' => $client['property_account_receivable'][0],

'invoice_line' => array(array(0, false, array('name' => "AAA")))

)));

$models->exec_workflow(

$db, $uid, $password,

'account.invoice', 'invoice_open',

$invoice_id);

client = models.execute_kw(

db, uid, password,

'res.partner', 'search_read',

[[['customer', '=', true]]],

{limit: 1, fields: %w(property_account_receivable property_payment_term property_account_position)}

)[0]

invoice_id = models.execute_kw(

db, uid, password,

'account.invoice', 'create', [{

partner_id: client['id'],

account_id: client['property_account_receivable'][0],

invoice_line: [[0, false, {name: "AAA"}]]

}])

models.exec_workflow(

db, uid, password,

'account.invoice', 'invoice_open', invoice_id)

final Map c = (Map)

((Object[])models.execute("execute_kw", asList(

db, uid, password,

"res.partner", "search_read",

asList(

asList(

asList("customer", "=", true))),

new HashMap() {{

put("limit", 1);

put("fields", asList(

"property_account_receivable",

"property_payment_term",

"property_account_position"

));

}}

)))[0];

final Integer invoice_id = (Integer)models.execute(

"execute_kw", asList(

db, uid, password,

"account.invoice", "create",

asList(new HashMap() {{

put("partner_id", c.get("id"));

put("account_id", ((Object[])c.get("property_account_receivable"))[0]);

put("invoice_line", asList(

asList(0, false, new HashMap() {{

put("name", "AAA");

}})

));

}})

));

models.execute(

"exec_workflow", asList(

db, uid, password,

"account.invoice", "invoice_open", invoice_id));Report printing

Available reports can be listed by searching the ir.actions.report.xml

model, fields of interest beingmodelthe model on which the report applies, can be used to look for available

reports on a specific modelnamehuman-readable report namereport_namethe technical name of the report, used to print it

Reports can be printed over RPC with the following information:the name of the report (report_name)

the ids of the records to include in the report

Python

PHP

Ruby

Java

invoice_ids = models.execute_kw(

db, uid, password, 'account.invoice', 'search',

[[('type', '=', 'out_invoice'), ('state', '=', 'open')]])

report = xmlrpclib.ServerProxy('{}/xmlrpc/2/report'.format(url))

result = report.render_report(

db, uid, password, 'account.report_invoice', invoice_ids)

report_data = result['result'].decode('base64')

$invoice_ids = $models->execute_kw(

$db, $uid, $password,

'account.invoice', 'search',

array(array(array('type', '=', 'out_invoice'),

array('state', '=', 'open'))));

$report = ripcord::client("$url/xmlrpc/2/report");

$result = $report->render_report(

$db, $uid, $password,

'account.report_invoice', $invoice_ids);

$report_data = base64_decode($result['result']);

require 'base64'

invoice_ids = models.execute_kw(

db, uid, password,

'account.invoice', 'search',

[[['type', '=', 'out_invoice'], ['state', '=', 'open']]])

report = XMLRPC::Client.new2("#{url}/xmlrpc/2/report").proxy

result = report.render_report(

db, uid, password,

'account.report_invoice', invoice_ids)

report_data = Base64.decode64(result['result'])

final Object[] invoice_ids = (Object[])models.execute(

"execute_kw", asList(

db, uid, password,

"account.invoice", "search",

asList(asList(

asList("type", "=", "out_invoice"),

asList("state", "=", "open")))

));

final XmlRpcClientConfigImpl report_config = new XmlRpcClientConfigImpl();

report_config.setServerURL(

new URL(String.format("%s/xmlrpc/2/report", url)));

final Map result = (Map)client.execute(

report_config, "render_report", asList(

db, uid, password,

"account.report_invoice",

invoice_ids));

final byte[] report_data = DatatypeConverter.parseBase64Binary(

(String)result.get("result"));

Note

the report is sent as PDF binary data encoded in base64, it must be

decoded and may need to be saved to disk before use

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值