├── README.md ├── tests ├── test.js └── search.js └── lib └── odoo.js /README.md: -------------------------------------------------------------------------------- 1 | ## odoo JSON-RPC Client for NodeJS 2 | 3 | [![Join the chat at https://gitter.im/Covetel/odoo-client](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Covetel/odoo-client?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | ### SYNOPSIS 6 | 7 | ```js 8 | var odoo = require('./lib/odoo.js'); 9 | 10 | var opts = { 11 | login: 'admin', 12 | password: '123321...', 13 | db: 'cooperativa-test', 14 | host: 'localhost', 15 | port: '8069' 16 | } 17 | 18 | // create the client 19 | var client = new odoo(opts); 20 | 21 | // auth 22 | client.auth(callback); 23 | 24 | // show databases 25 | client.database_getlist(callback); 26 | 27 | // get model 28 | 29 | function callback (err,response){ 30 | console.dir(response); 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | var odoo = require('../lib/odoo.js'); 2 | 3 | var opts = { 4 | login: 'admin', 5 | password: '123321...', 6 | db: 'cooperativa-test', 7 | host: 'localhost', 8 | port: '8069' 9 | } 10 | 11 | // create the client 12 | var client = new odoo(opts); 13 | 14 | // auth 15 | client.auth(on_auth); 16 | 17 | // show databases 18 | //client.database_getlist(callback); 19 | 20 | function callback (err,response){ 21 | console.dir(response.result); 22 | } 23 | 24 | function on_auth (err,response,sid){ 25 | if (err) throw err; 26 | 27 | if (response.result.uid){ 28 | //save session 29 | client.session_id = response.result.session_id; 30 | client.context = response.result.user_context; 31 | client.sid = sid; 32 | 33 | // Get model struct 34 | //client.get_model('res.partner',callback); 35 | 36 | // Create record 37 | var args = [ 38 | { 39 | "journal_id" : 6, 40 | "credit" : 0, 41 | "ref" : false, 42 | "date" : "2014-04-28", 43 | "move_id" : false, 44 | "name" : "nombre", 45 | "period_id" : 5, 46 | "account_id" : 5, 47 | "debit" : 100, 48 | "statement_id" : false, 49 | "partner_id" : false, 50 | "date_maturity" : false, 51 | "account_tax_id" : false, 52 | "analytic_account_id" : false 53 | } 54 | ]; 55 | 56 | client._create('account.move.line', args, undefined, undefined, callback); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/search.js: -------------------------------------------------------------------------------- 1 | var odoo = require('../lib/odoo.js'); 2 | 3 | var opts = { 4 | login: 'admin', 5 | password: '123321...', 6 | db: 'cooperativa-test', 7 | host: 'localhost', 8 | port: '8069' 9 | } 10 | 11 | // create the client 12 | var client = new odoo(opts); 13 | 14 | // auth 15 | client.auth(on_auth); 16 | 17 | function callback (err,response){ 18 | if (err) throw err; 19 | 20 | console.dir(response.result); 21 | } 22 | 23 | function on_auth (err,response,sid){ 24 | if (err) throw err; 25 | 26 | if (response.result.uid){ 27 | //save session 28 | client.session_id = response.result.session_id; 29 | client.context = response.result.user_context; 30 | client.sid = sid; 31 | 32 | // Search an account by code equal 33 | client.search('account.account', callback, ['code','=','1.1.2']); 34 | 35 | // Search an account by code equal 36 | client._search('account.account', callback, ['code','=','1.1.2'], ['id','name']); 37 | 38 | // Search an account by code is not equal 39 | client._search('account.account', callback, ['code','!=','1.1.2'], ['id','name']); 40 | 41 | // search an account by code contains 1.1.2 42 | client._search('account.account', callback, ['code','ilike','1.1.2'], ['id','name']); 43 | 44 | // search an account by code contains 1.1.2 45 | client._search('account.account', callback, ['code','not like','1.1.2'], ['id','name']); 46 | 47 | // search an account by code contains 1.1.2 48 | client._search('account.account', callback, undefined, ['id','name']); 49 | 50 | // search all 51 | client._search('account.account', callback, undefined, undefined, 0, 0); 52 | 53 | // search all sort by field type asc 54 | client._search('account.account', callback, undefined, ['id', 'name', 'type'], 0, 0, 'type ASC'); 55 | 56 | // search all sort by field type desc 57 | client._search('account.account', callback, undefined, ['id', 'name', 'type'], 0, 0, 'type DESC'); 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/odoo.js: -------------------------------------------------------------------------------- 1 | var jayson = require('jayson'); 2 | var http = require('http'); 3 | var _ = require('underscore'); 4 | 5 | module.exports = (function (){ 6 | 7 | function odoo(opts){ 8 | this.opts = opts; 9 | this.session_id = ''; 10 | this.context = ''; 11 | this.sid = ''; 12 | 13 | if (opts && opts.port){ 14 | this.port = opts.port; 15 | } else { 16 | this.port = '8069'; 17 | } 18 | 19 | if (opts && opts.host){ 20 | this.host = opts.host; 21 | } else { 22 | this.host = 'localhost'; 23 | } 24 | 25 | this.protocol = 'http'; 26 | this.base_location = this.protocol + '://' + this.host + ':' + this.port; 27 | 28 | this.paths = { 29 | 'auth': this.base_location + '/web/session/authenticate', 30 | 'databases': this.base_location + '/web/database/get_list', 31 | 'dataset_call_kw': this.base_location + '/web/dataset/call_kw', 32 | }; 33 | } 34 | 35 | odoo.prototype.database_getlist = function (cb) { 36 | var client = jayson.client.http(this.paths.databases); 37 | 38 | client.request('call',{'session_id': '', 'context':{}}, 'r8', cb); 39 | 40 | }; 41 | 42 | odoo.prototype.auth = function (cb){ 43 | 44 | var params = { 45 | 'db': this.opts.db, 46 | 'login': this.opts.login, 47 | 'password': this.opts.password, 48 | 'base_location': this.base_location, 49 | 'session_id': '', 50 | 'context': {} 51 | } 52 | 53 | var json = JSON.stringify({ 54 | 'jsonrpc': '2.0', 55 | 'method': 'call', 56 | 'params': params 57 | }); 58 | 59 | var options = { 60 | 'host': this.host, 61 | 'port': this.port, 62 | 'path': '/web/session/authenticate', 63 | 'method': 'POST', 64 | 'headers': { 65 | "Content-Type": "application/json", 66 | "Accept": "application/json", 67 | "Content-Length": json.length, 68 | } 69 | }; 70 | 71 | 72 | var req = http.request(options, function(res){ 73 | var response = ''; 74 | 75 | res.setEncoding('utf8'); 76 | 77 | var sid = res.headers['set-cookie'][0].split(';')[0]; 78 | 79 | res.on('data', function (chunk){ 80 | response += chunk; 81 | }); 82 | 83 | res.on('end',function(){ 84 | if (res.statusCode < 200 || res.statusCode >= 300) { 85 | var err = new Error(response); 86 | err.code = res.statusCode; 87 | return cb(err); 88 | } else { 89 | return cb(null,JSON.parse(response),sid); 90 | } 91 | }); 92 | }); 93 | 94 | req.write(json); 95 | } 96 | 97 | odoo.prototype.rpc = function(path, cb, params, options) { 98 | 99 | params = params || {}; 100 | 101 | options = options || { 102 | host: this.host, 103 | port: this.port, 104 | path: path || '/', 105 | headers: { 106 | "Content-Type": "application/json", 107 | "Accept": "application/json", 108 | } 109 | }; 110 | 111 | if (this.sid){ 112 | var sid = this.sid + ';'; 113 | options.headers.Cookie = this.sid + ';'; 114 | } 115 | 116 | _.defaults(params,{ 117 | context: this.context || {}, 118 | session_id: this.session_id || {}, 119 | }); 120 | 121 | var json_client = jayson.client.http(options); 122 | 123 | return json_client.request('call', params, _.uniqueId('r'), cb); 124 | }; 125 | 126 | 127 | odoo.prototype._call = function (model, method, cb, args, kwargs){ 128 | args = args || [ 129 | false, 130 | "tree", 131 | { 132 | "uid": this.context.uid, 133 | "lang": this.context.lang, 134 | "tz": this.context.tz, 135 | }, 136 | true 137 | ]; 138 | 139 | kwargs = kwargs || {}; 140 | 141 | params = { 142 | "kwargs": kwargs, 143 | "args": args, 144 | "model": model, 145 | "method": method, 146 | } 147 | 148 | this.rpc('/web/dataset/call_kw', cb, params); 149 | } 150 | 151 | odoo.prototype._create = function (model, args, kwargs, cb) { 152 | this._call(model, "create", cb, args, kwargs); 153 | } 154 | 155 | 156 | odoo.prototype.get_model = function (model,cb){ 157 | this._call(model,"fields_view_get", cb); 158 | } 159 | 160 | 161 | /** 162 | * Basic Search 163 | * 164 | */ 165 | odoo.prototype._search = function (model,cb,filter,fields,offset,limit,sort){ 166 | 167 | // example of filter = ["code", "=", "1.1.2"] 168 | 169 | fields = fields || []; 170 | 171 | var domain = []; 172 | 173 | if (filter){ 174 | domain.push(filter); 175 | } 176 | 177 | var params = { 178 | "model": model, 179 | "domain": domain, 180 | "sort": sort, 181 | "fields": fields, 182 | "limit": limit || 80, 183 | "offset": offset || 0 184 | }; 185 | 186 | this.rpc('/web/dataset/search_read', cb, params); 187 | 188 | } 189 | 190 | return odoo; 191 | })(); 192 | --------------------------------------------------------------------------------