Memanggil API Odoo dengan PHP

Secara default odoo sudah menyediakan api. Jadi jika kita ingin menghubungkan odoo dengan program lain kita tidak perlu membuat api sendiri. Tinggal panggil saja api yang sudah disediakan oleh odoo. Pada tutorial ini saya aka membahas bagaimana memanggil api odoo dengan bahasa pemrograman PHP.

Odoo sendiri sudah memiliki dokumentasi untuk penggunaan api, silakan lihat disini. Tetapi dari dokumentasi tersebut ada beberapa hal yang menurut saya tidak dicantumkan. Seperti beda cara panggil method dengan decorator @api.model dengan method dengan decorator @api.multi. Oleh karena itu saya akan menulis tutorial ini berdasarkan dokumentasi odoo dengan beberapa modifikasi.

Agar bisa memanggil api odoo dari PHP kita butuh xml rpc client, di dokumentasi, odoo menggunakan Ripcord, silakan download ripcord disini.

Authentication

Untuk memanggil odoo api, kita butuh id user. Oleh karena itu kita perlu memanggil method authenticate terlebih dahulu untuk mendapatkan id user tersebut, jika sudah tahu id suatu user tidak memanggil method authenticate tidak apa-apa.

Untuk melakukan authentication kita perlu menyediakan parameter-parameter ini.

  1. URL / Alamat Server

    Isi alamat server odoo, termasuk port jika ada. Misal http://33.33.33.33:8069 atau https://ngasturi.id:8069. Karena pada tutorial ini server odoo saya berada di komputer lokal, jadi saya isi http://localhost:8069.

  2. Nama Database

    Isi nama database dimana kita akan memanipulasi data. Silakan masuk ke link alamat_server/web/database/selector untuk melihat daftar nama database yang tersedia.

    Memilih database pada odoo

    Dari gambar diatas terlihat bahwa saya memiliki 2 database. Saya akan menggunakan database tutorial_dua

  3. User Email dan Password

    Email dan password disini adalah email yang digunakan untuk login pada odoo lewat web browser. Jadi jika kita bisa menggunakan email dan password tersebut untuk login pada odoo lewat web browser seharusnya email dan password tersebut juga bisa digunakan untuk memanggil api odoo.

    Perlu kita ketahui hak akses tetap berlaku saat kita memanggil api odoo. Misal jika user tersebut tidak bisa create Sale Order lewat ERP (web browser) tentu juga tidak bisa create Sale Order lewat api.

Sebagai contoh saya memiliki user seperti pada gambar dibawah ini.

Tampilan master user pada odoo

Terlihat email user tersebut adalah agus@gmail.com dengan id 6 (lihat parameter id pada address bar browser). Anggap saja password-nya adalah 123 jika kita memanggil method authenticate seharusnya hasilnya juga 6. Berikut ini source code PHP untuk melakukan authentication.

<?php 
	require_once('ripcord-master/ripcord.php');

	$url = 'http://localhost:8069';
	$db = 'tutorial_dua';
	$email = 'agus@gmail.com';
	$password = '123';

	$common = ripcord::client("$url/xmlrpc/2/common");
	$uid = $common->authenticate($db, $email, $password, []);
	
	if(!empty($uid)){
		echo "Berhasil login dengan User ID : " . $uid . '</br>';
	}else{
		echo "Gagal login";
	}
?>

Pada dasarnya saat kita memanggil api odoo, kita menjalankan public method pada suatu model. Oleh karena itu saya sarankan untuk membaca source code odoo, untuk melihat public method apa saja yang tersedia, yang memungkinkan untuk kita panggil / jalankan lewat api.

Berikut ini adalah format pemanggilan api odoo.

$models = ripcord::client("$url/xmlrpc/2/object");
$result = $models->execute_kw(db_name, user_id, user_password, model_name, public_method_name, record_ids, positional_argument, keyword_argument);

Berikut ini adalah penjelasan mengenai argument yang dimasukkan pada method execute_kw diatas

  1. db_name

    Nama database dimana kita akan memanipulasi data. Sama dengan saat kita melakukan authentication. Tipe datanya adalah string.

  2. user_id

    Id user yang kita dapatkan saat melakukan authentication. Jika sudah tahu id user tidak perlu melakukan authentication. Tipe datanya adalah integer.

  3. user_password

    Password yang dipakai login oleh user. Sama dengan password yang dipakai saat melakukan authentication. Tipe datanya adalah string.

  4. model_name

    Nama model yang akan kita manipulasi datanya. Untuk melihat daftar model pada odoo masuk menu Setting >> Technical >> Database Structure >> Models (sebelumnya harus masuk mode debug terlebih dahulu). Tipe datanya adalah string.

  5. public_method_name

    Untuk mengetahui nama method kita harus baca source code odoo. Sebagai contoh ini adalah source code model odoo yang ditulis dengan bahasa python. Semua method yang ada di Class BaseModel di file tersebut bisa dipanggil dari semua model pada odoo.

    Pada python public method adalah method yang tidak diawali dengan underscore misal method search pada source code odoo pada link diatas, seperti dibawah ini.

    @api.model
    @api.returns('self',
        upgrade=lambda self, value, args, offset=0, limit=None, order=None, count=False: value if count else self.browse(value),
        downgrade=lambda self, value, args, offset=0, limit=None, order=None, count=False: value if count else value.ids)
    def search(self, args, offset=0, limit=None, order=None, count=False):
    

    Method ini digunakan untuk mencari data pada database, dimana method ini akan return id suatu model yang sesuai dengan kriteria pencarian yang dibungkus dalam sebuah array. Berikut ini adalah contoh kode memanggil public method search pada model res.partner

    <?php 
    	require_once('ripcord-master/ripcord.php');
    
    	$url = 'http://localhost:8069';
    	$db = 'tutorial_dua';
    	$email = 'agus@gmail.com';
    	$password = '123';
    
    	$common = ripcord::client("$url/xmlrpc/2/common");
    	$uid = $common->authenticate($db, $email, $password, []);
    	
    	if(!empty($uid)){
    		// echo "Berhasil login dengan User ID : " . $uid . '</br>';
    
    		$models = ripcord::client("$url/xmlrpc/2/object");
    
    		// contoh memanggil method public search
    		$partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'search', [[]]);
    
    		echo "<pre>" . print_r($partners, true) . "</pre>";
    
    	}else{
    		echo "Gagal login";
    	}
    ?>
    

    Kira-kira hasilnya akan seperti ini.

    Hasil memanggil API pada odoo

    Private method adalah method yang diawal dengan underscore. Sebagai perbandingan, masih pada file yang sama terdapat private method _search seperti dibawah ini

    @api.model
    def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
    

    Jika kita memanggil private method tersebut seperti kode dibawah ini

    <?php 
    	require_once('ripcord-master/ripcord.php');
    
    	$url = 'http://localhost:8069';
    	$db = 'tutorial_dua';
    	$email = 'agus@gmail.com';
    	$password = '123';
    
    	$common = ripcord::client("$url/xmlrpc/2/common");
    	$uid = $common->authenticate($db, $email, $password, []);
    	
    	if(!empty($uid)){
    		// echo "Berhasil login dengan User ID : " . $uid . '</br>';
    
    		$models = ripcord::client("$url/xmlrpc/2/object");
    
    		// contoh memanggil method private _search, seharusnya akan muncul pesan error
    		$partners = $models->execute_kw($db, $uid, $password, 'res.partner', '_search', [[]]);
    
    		echo "<pre>" . print_r($partners, true) . "</pre>";
    
    	}else{
    		echo "Gagal login";
    	}
    ?>
    

    Akan return error seperti gambar dibawah ini

    Tampilan error saat memanggil method private lewat API pada odoo
  6. record_ids

    Argumen ini kita isi atau tidak tergantung decorator suatu method yang akan kita panggil. Jika suatu method diawal dengan decorator @api.model atau @api.model_create_multi kita tidak perlu mengisi argumen ini, jika kita isi akan return error. Method search diatas menggunakan decorator @api.model jadi kita tidak perlu mengisi argumen ini.

    Jika suatu method tidak diawali decorator @api.model atau @api.model_create_multi kita harus mengisi argumen ini. Misal method write seperti dibawah ini (masih pada source code odoo pada link diatas)

    def write(self, vals):
    

    Method write ini gunakan untuk meng-update suatu model. Misal kita memiliki 2 partner (Customer) dengan id 9 dan 10. Jika kita ingin mengganti alamat kedua partner tersebut dengan nilai yang sama kita bisa menggunakan kode seperti dibawah ini

    <?php 
    	require_once('ripcord-master/ripcord.php');
    
    	$url = 'http://localhost:8069';
    	$db = 'tutorial_dua';
    	$email = 'agus@gmail.com';
    	$password = '123';
    
    	$common = ripcord::client("$url/xmlrpc/2/common");
    	$uid = $common->authenticate($db, $email, $password, []);
    	
    	if(!empty($uid)){
    		// echo "Berhasil login dengan User ID : " . $uid . '</br>';
    
    		$models = ripcord::client("$url/xmlrpc/2/object");
    
    		$partner_record_ids = [9,10];
    		$partner_value = [
    			'street' => 'Jl. Rajawali 12',
    			'city' => 'Surabaya'
    		];
    		$values = [$partner_record_ids, $partner_value];
    
    		$partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'write', $values);
    
    		echo "<pre>" . print_r($partners, true) . "</pre>";
    
    	}else{
    		echo "Gagal login";
    	}
    ?>
    

    Dari kode diatas bisa kita lihat bahwa nilai record_ids ini adalah integer yang dibungkus array. Selanjutnya dibungkus array lagi jadi satu dengan positional_argument. Perlu dicatat record_ids harus diletakkan lebih dulu dari positional_argument

  7. positional_argument

    Positional argument adalah variabel yang dimasukkan pada suatu method secara berurutan sesuai dengan urutan / posisi argumen / parameter tersebut ditulis pada source code asli. Sebagai contoh pada method search diatas 3 argumen / parameter pertama adalah args offset dan limit, jika kita ingin menset nilai limit maka kita juga harus menset nilai offset terlepas kita ingin mengatur nilai offset atau tidak. Karena offset ditulis terlebih dahulu, sedangkan parameter args harus diisi karena tidak ada nilai default. Positional argumen ini terkadang harus diawali dengan record_ids yang berupa id atau primary key suatu model. Lihat penjelasan sebelumnya.

    <?php 
    	require_once('ripcord-master/ripcord.php');
    
    	$url = 'http://localhost:8069';
    	$db = 'tutorial_dua';
    	$email = 'agus@gmail.com';
    	$password = '123';
    
    	$common = ripcord::client("$url/xmlrpc/2/common");
    	$uid = $common->authenticate($db, $email, $password, []);
    	
    	if(!empty($uid)){
    		$models = ripcord::client("$url/xmlrpc/2/object");		
    
    		// contoh memanggil method menggunakan positional argument
    		$partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'search', [[],0,2]);
    
    		echo "<pre>" . print_r($partners, true) . "</pre>";
    
    	}else{
    		echo "Gagal login";
    	}
    ?>
    
  8. keyword_argument

    Keyword argument adalah argument yang memiliki nilai default. Keyword argument bisa ditulis jadi satu dengan positional argument atau ditulis terpisah. Jika ditulis jadi satu dengan positional argument maka kita harus memperhatikan urutan penulisan argument ini pada source code odoo. Jika ditulis terpisah kita bisa mengabaikan urutan dan bisa hanya menulis argument yang kita butuhkan saja. Keyword argument ditulis dalam bentuk asociative array seperti dibawah ini.

    <?php 
    	require_once('ripcord-master/ripcord.php');
    
    	$url = 'http://localhost:8069';
    	$db = 'tutorial_dua';
    	$email = 'agus@gmail.com';
    	$password = '123';
    
    	$common = ripcord::client("$url/xmlrpc/2/common");
    	$uid = $common->authenticate($db, $email, $password, []);
    	
    	if(!empty($uid)){
    		$models = ripcord::client("$url/xmlrpc/2/object");
    
    		// contoh memanggil method menggunakan keyword argument
    		$partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'search', [[]], ['order' => 'name desc','limit' => 2]);
    
    		echo "<pre>" . print_r($partners, true) . "</pre>";
    
    	}else{
    		echo "Gagal login";
    	}
    ?>
    

General Method

Berikut ini adalah method-method umum pada odoo yang bisa dipanggil dari semua model.

  1. Create

    Method ini digunakan untuk memasukkan data ke database. Berikut ini adalah source code asli penulisan methodnya.

    @api.model_create_multi
    @api.returns('self', lambda value: value.id)
    def create(self, vals_list):
    

    Method create ini menggunakan decorator @api.model_create_multi jadi kita tidak perlu memasukkan record_ids. Method ini hanya terdiri dari satu parameter berupa asociative array. Method ini akan return primary key / id dari data yang berhasil dimasukkan. Berikut ini adalah contoh menggunakan method Create untuk input master partner.

    <?php 
    	require_once('ripcord-master/ripcord.php');
    
    	$url = 'http://localhost:8069';
    	$db = 'tutorial_dua';
    	$email = 'agus@gmail.com';
    	$password = '123';
    
    	$common = ripcord::client("$url/xmlrpc/2/common");
    	$uid = $common->authenticate($db, $email, $password, []);
    	
    	if(!empty($uid)){
    		$models = ripcord::client("$url/xmlrpc/2/object");
    
    		// contoh memanggil method create pada model res.partner
    		$values = [
    			'name' => 'Ngasturi',
    			'street' => 'Jl. Semolowaru 12',
    			'city' => 'Surabaya'
    		];
    		$partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'create', [$values]);
    
    		echo "<pre>" . print_r($partners, true) . "</pre>";
    
    	}else{
    		echo "Gagal login";
    	}
    ?>
    
  2. Write

    Method ini digunakan untuk mengupdate suatu data pada database. Sama dengan method create, method ini juga terdiri dari satu parameter dengan nilai berupa asociative array, tetapi kita juga harus memasukkan record_ids. Silakan lihat kode sebelumnya pada bagian record_ids

  3. Copy

    Method ini digunakan untuk men-duplicate suatu data pada database. Berikut ini adalah source code asli penulisan methodnya.

    @api.returns('self', lambda value: value.id)
    def copy(self, default=None):
    

    Saat memanggil method ini kita harus memasukkan record_ids yaitu id / primary key data yang akan kita duplicate. Kita juga bisa memasukkan keyword argument default dalam bentuk asociative array. Jika argument default ini diisi setelah data berhasil diduplicate nilainya akan diupdate sesuai dengan value pada argument default seperti pada contoh kode dibawah ini

    // contoh memanggil method copy
    $partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'copy', [[14]], ['default' => ['street' => 'Jl. Ahamad Yani 14']]);
    
    echo "<pre>" . print_r($partners, true) . "</pre>";
    
  4. Unlink

    Method ini digunakan untuk menghapus data di database. Method ini tidak memiliki argument. Tetapi kita harus memasukkan record_ids yang berupa id / primary key yang akan kita hapus.

    $partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'unlink', [[14]]);
    
  5. Search

    Method ini digunakan untuk mencari data pada database. Method ini akan return id yang dibungkus dalam array jika kriteria pencarian sesuai. Method ini memiliki beberapa argument, yaitu :

    • Args

      Argument ini biasa disebut domain. Yaitu array yang nantinya akan diubah oleh odoo sebagai klausa where saat query ke database.

    • Offset dan Limit

      Argument ini digunakan untuk membatasi data yang ditampilkan. Jika kedua argument ini dikombinaksikan bisa digunakan untuk membuat paging. Tipe datanya adalah integer.

    • Order

      Argument ini digunakan untuk mengatur bagaimana data diurutkan. Tipe datanya adalah string. Setiap klausa order harus dipisahkan dengan koma.

    • Count

      Jika diset True maka akan return jumlah hasil pencarian alih-alih id model.

    Berikut ini adalah contoh kode memanggil method search dengan domain dan beberapa keyword argument.

    $domain = [
    	['email', 'ilike', 'gmail'],
    	['city', '=', 'Surabaya']
    ];
    $kwargs = ['order' => 'name desc, street asc', 'limit' => 2];
    $partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'search', [$domain], $kwargs);
    
  6. search_count

    Sama dengan method search method ini digunakn untuk mencari data pada database. Tapi nilai yang direturn adalah jumlah-nya, bukan data-nya. Berikut ini adalah source code asli penulisan methodnya.

    @api.model
    def search_count(self, args):
    

    Method ini hanya memiliki 1 argument yang berupa domain. Sama dengan argument args pada method search. Berikut ini adalah contoh pemanggilan method ini

    $domain = [
    	['email', 'ilike', 'gmail'],
    	['city', '=', 'Surabaya']
    ];
    $partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'search_count', [$domain]);
    
  7. search_read

    Sama dengan method search method ini juga digunakan untuk mencari data pada database. Tetapi jika pada method search data yang direturn adalah id / primary key, pada method ini kita bisa mengatur field apa yang direturn. Berikut ini adalah source code asli penulisan methodnya.

    @api.model
    def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
    

    Berikut ini adalah contoh pemanggilan method ini.

    $domain = [
    	['email', 'ilike', 'gmail'],
    	['city', '=', 'Surabaya']
    ];
    $kwargs = ['order' => 'name desc, street asc', 'domain' => $domain, 'fields' => ['name', 'city', 'street', 'email']];
    $partners = $models->execute_kw($db, $uid, $password, 'res.partner', 'search_read', [], $kwargs);
    

    Kira – kira hasilnya akan seperti ini

    Hasil memanggil method search_read pada odoo lewat API

Specific Method

Selain method-method umum yang bisa digunakan pada semua model, terdapat juga method-method yang hanya tersedia pada model tertentu. Misal method action_confirm yang dieksekusi saat kita melakukan klik pada tombol Confirm pada model sale.order berikut ini.

def action_confirm(self):
    if self._get_forbidden_state_confirm() & set(self.mapped('state')):
        raise UserError(_(
            'It is not allowed to confirm an order in the following states: %s'
        ) % (', '.join(self._get_forbidden_state_confirm())))

    for order in self.filtered(lambda order: order.partner_id not in order.message_partner_ids):
        order.message_subscribe([order.partner_id.id])
    self.write(self._prepare_confirmation_values())

    # Context key 'default_name' is sometimes propagated up to here.
    # We don't need it and it creates issues in the creation of linked records.
    context = self._context.copy()
    context.pop('default_name', None)

    self.with_context(context)._action_confirm()
    if self.env.user.has_group('sale.group_auto_done_setting'):
        self.action_done()
    return True

Cara memanggil specific method tidak berbeda dengan general method.

Masih banyak method yang bisa dipanggil lewat api. Baik yang bersifat general yang tersedia di semua model atau hanya tersedia pada model tertentu. Lebih detailnya silakan baca source code odoo.

Download source code disini

Tulisan Serupa

6 Replies to “Memanggil API Odoo dengan PHP”

    1. Kalau mau pakai api key sebagai alternatif password hanya bisa dilakukan di odoo 14. Silakan baca dokumentasinya di sini. Untuk odoo versi lain mungkin harus override fungsi bawaan odoo.

Leave a Reply