Pada odoo ada 2 cara untuk menghitung nilai suatu field secara otomatis. Yaitu menggunakan decorator onchange atau field parameter compute.
Gunakan decorator onchange jika kita ingin nilai suatu field berubah jika nilai field lain berubah. Misal kita memiliki 3 field seperti ini
# -*- coding: utf-8 -*- from odoo import api, fields, models, _ class MyModel(models.Model): _name = 'my.model' field_1 = fields.Integer(string='Field 1') field_2 = fields.Integer(string='Field 2') result = fields.Integer(string='Result')
Jika kita ingin nilai dari field result berubah jika nilai dari field_1 atau field_2 berubah kita bisa menggunakan decorator onchange seperti dibawah ini
@api.onchange('field_1', 'field_2') def calculate_result(self): self.result = self.field_1 + self.field_2
Masukkan field yang digunakan sebagai trigger pada decorator onchange sebagai parameter. Jumlah field yang bisa dimasukkan bebas. Selanjutnya diikuti method dengan nama bebas. Saat program berjalan, jika salah satu dari field yang digunakan sebagai trigger nilainya berubah, method tersebut, dalam contoh kasus ini adalah calculate_result akan dieksekusi.
Berikut ini adalah contoh tampilan nilai yang sudah diubah secara otomatis dengan decorator onchange
Field yang dihitung dengan decorator onchange masih bisa diubah oleh user, baik dari frontend atau dari backend (misal lewat perintah SQL) dan nilainya akan disimpan oleh odoo selama nilai dari field trigger tidak berubah. Berikut ini adalah contoh tampilan field yang dihitung dengan decorator onchange tapi diubah lagi oleh user kemudian disimpan.
Method yang ditandai dengan decorator onchange hanya dipanggil jika nilai field trigger diubah dari frontend, atau saat form tersebut diedit. Jadi jika nilai field_1 diubah dari model lain dengan python atau lewat perintah SQL nilai dari field result tidak akan berubah.
Seperti disebutkan sebelumnya bahwa field yang dihitung dengan decorator onchange masih bisa diubah oleh user, jadi kita mungkin perlu menambahkan attribute readonly. Tetapi field yang ditandai dengan attribute readonly nilainya tidak akan disimpan di database. Jika ingin nilai tersebut disimpan pastikan untuk menggunakan attribute force_save seperti dibawah ini.
<field name="result" readonly="1" force_save="1" />
Selanjutnya kita juga bisa menggunakan field parameter compute untuk menghitung nilai suatu field secara otomatis. Seperti pada kode dibawah ini
# -*- coding: utf-8 -*- from odoo import api, fields, models, _ class MyModel(models.Model): _name = 'my.model' field_1 = fields.Integer(string='Field 1') field_2 = fields.Integer(string='Field 2') result = fields.Integer(string='Result', compute='compute_result') def compute_result(self): for rec in self: rec.result = rec.field_1 + rec.field_2
Berbeda dengan decorator onchange saat menggunakan field parameter compute pastikan loop parameter self. Karena jika tidak, akan terjadi error expected singleton jika data pada model tersebut banyak. Jadi hindari menggunakan kode seperti dibawah ini
result = fields.Integer(string='Result', compute='compute_result') def compute_result(self): self.result = self.field_1 + self.field_2
Field yang ditandai dengan field parameter compute secara otomatis akan jadi readonly. Sehingga tidak ada kemungkinan bagi user untuk mengubah nilai field tersebut dari frontend.
Field yang ditandai dengan field parameter compute, secara default nilainya tidak akan berubah sampai form tersebut disimpan. Saat masih dalam mode create / edit, nilai field tersebut tidak akan berubah karena method compute belum dipanggil
Method compute secara default dipanggil pada proses read. Yaitu saat kita buka tree view atau form view tapi tidak sedang dalam mode create atau edit. Setelah kita klik tombol Save, dan kita keluar dari mode create / edit barulah nilainya berubah, seperti pada gambar dibawah ini
Tetapi ada juga kelebihannya, yaitu jika kita ubah salah satu field yang dijadikan dasar perhitungan dari backend, dengan kode python dari model apapun atau dari database lewat perintah SQL, nilainya akan selalu berubah jika kita buka form tersebut.
Dari kedua gambar diatas terlihat bahwa nilai dari result berubah walaupun nilai field_1 diubah dari database lewat perintah SQL. Hal ini tidak mungkin terjadi jika kita menggunakan decorator onchange.
Tetapi jika kita menginginkan nilai field result langsung berubah tanpa harus klik tombol save juga bisa, carannya gunakan decorator depends seperti dibawah ini.
# -*- coding: utf-8 -*- from odoo import api, fields, models, _ class MyModel(models.Model): _name = 'my.model' field_1 = fields.Integer(string='Field 1') field_2 = fields.Integer(string='Field 2') result = fields.Integer(string='Result', compute='compute_result') @api.depends('field_1', 'field_2') def compute_result(self): for rec in self: rec.result = rec.field_1 + rec.field_2
Penulisan decorator depends sama dengan decorator onchange. Yang berbeda dengan decorator onchange, jika nilai dari field trigger di ubah dari backend dengan python dari model apapun atau dengan perintah SQL nilai dari field result akan berubah.
Field yang ditandai dengan field parameter compute secara default tidak akan dibuatkan kolom di table database. Sehingga tidak memungkinkan bagi kita untuk memasukkan field tersebut pada perintah SQL.
Pada gambar diatas terlihat bahwa tidak ada kolom dengan nama result. Jika kita ingin field tersebut dibuatkan kolom pada table database, kita harus menambahkan field parameter store dengan nilai True, seperti pada gambar dibawah ini
result = fields.Integer(string='Result', compute='compute_result', store=True)
Sekarang field result sudah dibuatkan kolom. Sayangnya jika kita melakukan perubahan pada field trigger (field_1 atau field_2) lewat perintah SQL, field result nilainya tidak berubah, method compute tidak dipanggil. Sama dengan saat kita menggunakan decorator onchange
Tetapi jika kita mengubah field trigger tersebut dengan python dari model apapun, nilai dari field result akan berubah, method compute tetap dipanggil. Berbeda dengan saat kita menggunakan decorator onchange
Demikian tutorial penggunaan decorator onchange dan field parameter compute untuk menghitung nilai suatu field secara otomatis. Gunakan sesuai kebutuhan.
6 Replies to “Penggunaan onchange dan compute pada Odoo”
Hallo min saya masih belajar odoo terutama pada logic python, kalau ada case nya seperti ini harusnya gimana ya ?
“tarik semua kontrak perhitungan dimulai dari kontrak paling awal pada jenis yg sama jadi jika kontrak kedua jenisnya berubah perhitungan dimulai dari kontrak kedua tersebut”
Mohon bantuannya
Pastikan kamu bisa membuat SQL Query secara manual di PostgreSQL, jika hasil SQL Query sudah sesuai yang diharapkan, pelan-pelan ubah SQL Query tadi menjadi Odoo domain. Silakan baca tulisan ini untuk melihat tips mengubah SQL Query menjadi Odoo domain.
Halo min, mau tanya apakah onChange memungkinkan jika dilakukan pada model yang berbeda? semisal saya mengubah “partner_id” yang ada di model “sale.order” kemudian hal ini secara otomatis mentrigger model “stock.picking”?
Terima kasih
belum coba, tapi kalau menurutku sih mending pakai compute. atau override method write.
Untuk pembuatan / pengambilan data report lebih baik menggunakan Onchange atau Compute untuk datanya?
Tergantung skenarionya. Coba aja salah satu.