Menguji Domain pada Odoo

Pada odoo Domain adalah list yang berisi ekspresi tertentu yang digunakan untuk memfilter suatu data dari database. Umumnya domain akan diterjemahkan oleh odoo menjadi ekspresi SQL untuk mengisi klausa where. Misal kita memiliki domain seperti dibawah ini.

[('state','=','draft')]

Domain diatas jika diterapkan pada model sale.order akan jadi expresi SQL seperti ini

WHERE (
	("sale_order"."state" = 'draft')
)

Domain bisa digunakan pada python untuk mencari data tertentu pada suatu model, atau pada field selection untuk membatasi pilihan dropdown. Bisa juga pada file xml, misal pada search view untuk membatasi data yang tampil pada list / tree view.

Domain juga bisa digunakan untuk mengatur attribute suatu field, misal untuk mengatur attribute readonly untuk mengatur field agar bisa diedit atau tidak bisa diedit pada kondisi tertentu.

Sebagai programmer odoo memahami domain ini sangatlah vital. Sayangnya domain ini ditulis dalam Polish Notation. Dimana operator ditulis lebih dulu dari pada operand. Misal jika kita punya ekspresi 1 + 2, jika ditulis dalam Polish Notation akan jadi + 1 2. Bagi yang belum kenal Polish Notation hal ini sangat membingungkan, ini yang saya alami waktu awal-awal bekerja sebagai programmer odoo.

Oleh karena itu kita harus punya trick tersendiri untuk menulis domain ini.

Salah satu trick yang biasa saya gunakan adalah mengubah domain menjadi SQL, sehingga saya bisa menjalankannya di Postgre SQL langsung untuk melihat hasilnya. Dengan mengubah domain menjadi SQL saya bisa menganalisa domain yang saya tulis sudah menghasilkan query yang saya harapkan atau belum. Jika sudah tentu saya tinggal membandingkan hasil query dari SQL tersebut dengan hasil query original odoo sudah sama atau tidak.

Saya sudah mengupload module domain menjad SQL ini di Github, silakan download di sini. Kemudian install untuk mengikuti tutorial ini.

Sebelum menulis domain, pastikan kita sudah bisa membuat query yang benar. Kemudian ubah query tersebut menjadi domain. Selanjutnya dengan method get_query dari module domain_to_sql di atas, domain tersebut akan diubah menjadi SQL. Selanjutnya kita tinggal membandingkan SQL yang kita tulis sejak awal dengan SQL dari method get_query.

Tetapi cara diatas hanya perlu kita lakukan jika kondisi pada query yang kita buat terdapat operator OR. Jika tidak ada operator OR tidak perlu pusing-pusing, tulis saja domain langsung tanpa perlu membuat SQL di postgre sql atau menguji-nya dengan module domain_to_sql.

Misal kita memiliki SQL seperti ini

select id 
from sale_order 
where state = 'draft' and
partner_id = 10

Karena tidak terdapat operator OR kita bisa langsung menulis domain seperti dibawah ini, mengabaikan operator AND karena pada odoo default operator-nya adalah AND

[('state','=','draft'), ('partner_id','=',10)]

Sebagai contoh kasus misal kita ingin mencari Partner dengan nama mengandung kata agus atau Partner dengan alamat mengandung kata street 2 dan email mengandung kata gmail. Jika ditulis dalam bentuk SQL kita bisa menulisnya seperti ini

select id
from res_partner
where name ilike '%agus%' or
(street ilike '%street 2%' and email ilike '%gmail%')

Jika kita jalankan query diatas di PG Admin, hasilnya akan seperti ini

Lalu bagaimana cara mengubah SQL query diatas menjadi odoo domain ?

Dalam Polish Notation terdapat operator dan operand. Operator pada domain odoo hanya ada 2 yaitu AND dengan simbol ‘&’ dan OR dengan simbol ‘|’. Dalam SQL query diatas terdapat 2 operator yaitu OR dan AND.

Sedangkan operand adalah ekspresi yang terdiri dari 3 bagian untuk menentukan nilai True atau False. Dalam SQL query diatas terdapat tiga operand yaitu name ilike ‘%agus%’, street ilike ‘%street 2%’ dan email ilike ‘%gmail%’

Untuk membuat domain tulis semua operator dari SQL query diatas secara berurutan dalam sebuah array, seperti dibawah ini.

domain = ['|','&']

Kemudian tulis operand dalam bentuk tuple secara berurutan, seperti di bawah ini.

domain = ['|','&',('name','ilike','agus'),('street','ilike', 'street 2'), ('email', 'ilike', 'gmail')]

Kemudian panggil method get_query untuk melihat hasil SQL query dari domain diatas.

domain = ['|','&',('name','ilike','agus'),('street','ilike', 'Street 2'), ('email', 'ilike', 'gmail')]
query = self.env['res.partner'].get_query(domain)
print(query)

Hasilnya akan jadi seperti ini

SELECT "res_partner".id FROM "res_partner" WHERE (("res_partner"."active" = 'True')  AND  ((("res_partner"."name"::text ilike '%agus%')  AND  ("res_partner"."street"::text ilike '%Street 2%'))  OR  ("res_partner"."email"::text ilike '%gmail%')))

Dari kode diatas ternyata SQL query yang dihasilkan ditambah operand yang tidak kita tulis yaitu (“res_partner”.”active” = ‘True’). Odoo secara default hanya menampilkan data yang active saja, oleh karena itu operand diatas selalu muncul. Agar operand diatas tidak muncul, dalam artian kita mengabaikan status active atau non active suatu model, kita bisa menambahkan context active_test bernilai False seperti dibawah ini.

domain = ['|','&',('name','ilike','agus'),('street','ilike', 'Street 2'), ('email', 'ilike', 'gmail')]
query = self.env['res.partner'].with_context({'active_test': False}).get_query(domain)
print(query)

Sekarang kode diatas akan menghasilkan SQL query seperti ini

SELECT "res_partner".id FROM "res_partner" WHERE ((("res_partner"."name"::text ilike '%agus%')  AND  ("res_partner"."street"::text ilike '%Street 2%'))  OR  ("res_partner"."email"::text ilike '%gmail%'))

Terlihat operand (“res_partner”.”active” = ‘True’) sudah tidak tampil lagi. Tapi operator AND dan OR menghubungkan operand yang salah. Ini artinya domain yang kita tulis masih salah.

Jika hal ini terjadi coba geser-geser operator-nya. Mulai dari operator paling kanan yaitu operator AND, kira-kira seperti ini.

domain = ['|', ('name','ilike','agus'), '&', ('street','ilike', 'Street 2'), ('email', 'ilike', 'gmail')]
query = self.env['res.partner'].with_context({'active_test': False}).get_query(domain)
print(query)

Hasilnya seperti ini

SELECT "res_partner".id FROM "res_partner" WHERE (("res_partner"."name"::text ilike '%agus%')  OR  (("res_partner"."street"::text ilike '%Street 2%')  AND  ("res_partner"."email"::text ilike '%gmail%')))

Sekarang posisi operator sudah benar. Tinggal kita membandingkan hasil query dari odoo lewat method search dengan hasil query yang pertama kali kita buat.

Jika kita memanggil method search seperti dibawah ini

domain = ['|', ('name','ilike','agus'), '&', ('street','ilike', 'Street 2'), ('email', 'ilike', 'gmail')]
query = self.env['res.partner'].with_context({'active_test': False}).get_query(domain)
print('query====')
print(query)

result = self.env['res.partner'].with_context({'active_test': False}).search(domain)
print('result====')
print(result)

Hasilnya akan terlihat seperti ini

Terlihat pada instalasi odoo saya, partner yang memenuhi kriteria dari domain di atas adalah partner dengan id 9 dan 11. Sama dengan hasil SQL query yang pertama kali kita buat. Jadi domain yang kita tulis sudah benar.

Tulisan Serupa

Leave a Reply

Your email address will not be published. Required fields are marked *