[Odoo 10] Technical Documentation -Part 6-

Alhamdulillah kita lanjutkan kembali serial tutorial ini. InsyaAllah pada pertemuan kali ini, kita akan membahas tentang domain, compute field, dan default values.

Di odoo, domain berfungsi sebagai filter suatu kondisi pada record, sebagaimana halnya syntax where pada sql. Domain biasa di gunakan pada field-field relasi seperti Many2one, One2many, dan Many2many. Domain berbentuk list python (array), yang isinya kumpulan tuple dan setiap tuple mengandung pasangan antara nama field dan values nya. Contohnya seperti ini :


domain = [('sale_ok', '=', True), ('product_type', '=', 'service'), ('unit_price', '>=', 1000)]

Domain bisa kita tentukan di model dan view. Domain juga memiliki beberapa operator yaitu & (AND), | (OR) dan ! (NOT). Jika kita tidak mendefiniskan, maka defaultnya operator & (AND). Cara menggunakannya kita set di awal domain, contohnya seperti ini :


domain = ['|', ('product_type', '=', 'service'), ('unit_price', '>', 1000)]

# Searching product yang tipenya service ATAU harganya diatas 1000

domain = ['&', ('product_type', '=', 'service'), ('unit_price', '<', 1000)]

# Searching product yang tipenya service DAN harganya dibawah 1000

domain = ['|', ('product_type', '=', 'service'), '!', '&', ('unit_price', '>=', 1000), ('unit_price', '<=', 2000)]

# Searching product yang tipenya service ATAU harganya yang BUKAN di antara 1000 dan 2000

domain = [('name','=','ABC'), ('language.code','!=','en_US'), '|',('country_id.code','=','be'), ('country_id.code','=','de')]

# Searching partner yang namanya ABC DAN bahasanya SELAIN en_US (english) DAN berasal dari negara be (belgia) ATAU de (jerman)

Jika kita perhatikan, diantara nama field dan valuenya ada operator. Diantara operator yang di sediakan odoo adalah :

= : sama dengan

!= : tidak sama dengan

> : lebih besar dari

>= : lebih besar dari atau sama dengan

< : lebih kecil dari

<= : lebih kecil dari atau sama dengan

=? : menghasilkan nilai True jika valuenya None atau False

=like : sama seperti operator =, bisa ditambah valuenya dengan underscore (_) -imbuhan 1 karakter- dan persentage (%) -imbuhan banyak karakter-

like : yang mengandung (case sensitive)
# [(‘name’, ‘like’, ‘apa’)], hasilnya record = ‘apa’, ‘bapak’, ‘apakah’, dst. Bukan ‘Apa’, ‘APA’, dst
# [(‘name’, ‘like’, ‘apa’)] sama seperti [(‘name’, ‘=like’, ‘%apa%’)]

not like : tidak mengandung (case sensitive)

ilike : yang mengandung (tidak case sensitive)
# [(‘name’, ‘ilike’, ‘apa’)], hasilnya record = ‘apa’, ‘Apa’, ‘APA’, ‘Apakah’, ‘bapak’, dst.
# [(‘name’, ‘ilike’, ‘apa’)] sama seperti [(‘name’, ‘=ilike’, ‘%apa%’)]

not ilike : tidak mengandung (tidak case sensitive)

=ilike : gabungan antara operator = dan ilike
# [(‘name’, ‘=ilike’, ‘apa’)], hasilnya record = ‘apa’, ‘APA’, ‘Apa’, ‘APa’, ApA’, ‘aPa’, dst. Bukan ‘Apakah’, ‘papah’, ‘Bapak’, dst

in : menjadi bagian value dari list/array

not in : tidak menjadi value bagian dari list/array

child_of : anak dari _parent_name (record yang hirarki)

Penambahan i pada like menjadikan tidak case sensitive (mengabaikan huruf besar kecil), sedangkan penambahan = menjadikan hasil querynya sesuai jumlah digit value parameternya

Sekarang kita aplikasikan pada materi training kita. Sebelumnya kita telah membuat field instructor (Instruktur) pada object ‘training_sesi’ yang merefer ke menu Kontak. Tidak ada filter sama sekali disana, sehingga valuenya tidak memiliki perbedaan dengan field attendee_ids (Peserta). Oleh karna itu, kita akan memberikan filter pada field instructor (Instruktur) seperti berikut :



class Sesi(models.Model):
    ...
    
    instructor_id = fields.Many2one('res.partner', string="Instruktur", domain=[('instructor', '=', True)])
    attendee_ids = fields.Many2many('res.partner', string="Peserta", domain=[('instructor', '=', False)])
    
    ...


Setelah kita restart service odoo, maka buatlah beberapa kontak baru, lalu centang cekbox Instruktur kepada salah satunya. Maka kita akan melihat perbedaan saat pemilihan Intruktur dan Peserta. Jika Instruktur di centang, maka ia tidak dapat di pilih menjadi Peserta, begitu juga sebaliknya. Kemudian pada form Kontak di bawah field Instruktur ada tabel Menghadiri Sesi, kita ingin tabel ini mengikuti kondisi nilai field Instruktur, ketika dia di centang maka table Menghadiri Sesi harus menghilang (invisible), karna instrukur tidak bisa menjadi peserta. Caranya dengan menggunakan attribut attrs seperti dibawah ini :



	<record model="ir.ui.view" id="instruktur_form_view">
	<field name="name">res.partner.instruktur</field>
	<field name="model">res.partner</field>
	<field name="inherit_id" ref="base.view_partner_form"/>
	<field name="arch" type="xml">
		<notebook position="inside">
			<page string="Sessions">
				<group>
					<field name="instructor"/>
					<field name="session_ids" attrs="{'invisible': [('instructor', '=', True)]}"/>
				</group>
			</page>
		</notebook>
	</field>
	</record>
	

Update modul kita dengan code xml diatas (perhatikan id xml nya). Lakukan restart dan upgrade modul training_odoo, lalu refresh browser dan silahkan di coba. Attribut attrs diantaranya :

a. invisible : field akan menjadi tidak terlihat jika kondisi terpenuhi
b. readonly : field akan menjadi tidak bisa di edit jika kondisi terpenuhi
c. required : field akan menjadi mandatory jika kondisi terpenuhi

Attribut diatas dapat digunakan bersamaan seperti contoh :


<field name="partner_id" attrs="{'invisible': [('communication', '=', True)], 'required': [('payment_type', 'in', ('inbound', 'outbound'))], 'readonly': [('state', '!=', 'draft')]}}" />

Pada contoh sebelumnya kita telah membuat domain field Instruktur, sekarang kita akan tambahkan lagi domainnya agar lebih complex. Silahkan di update :



class Sesi(models.Model):
    ...
    
    instructor_id = fields.Many2one('res.partner', string="Instruktur", domain=['|', ('instructor', '=', True), ('category_id.name', 'ilike', "Pengajar")])
    
    ...


Domain yang kita tambahkan di atas artinya, field Instuktur nilainya dapat kita pilih JIKA kontak telah di centang cekbox Instrukturnya ATAU kontak terkait termasuk Category yang memiliki nama ‘Pengajar’. Category kontak bisa kita tentukan pada field Tags.

Karna kita belum membuat category / tags kontak, sekarang kita buat terlebih dahulu agar kita bisa pilih untuk mencoba domain yang kita buat. Tambahkan xml berikut pada file partner.xml :


		
	<menuitem id="kontak_tags_menu" name="Kontak Tags" parent="konfigurasi_menu" action="base.action_partner_category_form"/>
	
	<record model="res.partner.category" id="teacher1">
		<field name="name">Pengajar / Basic</field>
	</record>
	
	<record model="res.partner.category" id="teacher2">
		<field name="name">Pengajar / Advanced</field>
	</record>
		

Perhatikan coding diatas, terdiri dari 3 bagian. Pertama, membuat menu Kontak Tags. Kita bisa langsung HANYA membuat menu jika action dan view lainnya sudah di definiskan pada modul lain, karna category / tags merupakan object default odoo (res_partner_category) sebagaimana kontak (res_partner) maka kita cukup menginheritnya saja. Kecuali kita ingin menambahkan domain, view, dll pada action, maka kita kita perlu membuat ulang actionnya. Perintah inherite berada pada attribut :


action="base.action_partner_category_form"

Artinya menu tags yang kita buat ketika di klik, maka akan memanggil action atau event yang ada di modul base dengan id xml action_partner_category_form. Kita juga bisa menginherite attribute parent jika kita ingin meletakan menu kita di bawah menu terkait.

Bagian kedua dan ketiga adalah proses insert record / baris ke menu Category / Tags. Selain input manual user, kita juga bisa menambahkan record dari xml. Sekarang silahkan dicoba untuk memilih salah satu dari 2 kondisi yaitu centang cekbox Instruktur atau tentukan tags Pengajar.

Selanjutnya kita akan membuat field compute dengan nama ‘taken_seats’ seperti berikut :




class Sesi(models.Model):
    
    ...
    
    taken_seats = fields.Float(string="Kursi Terisi", compute='_taken_seats')
    
    ...
    
    @api.depends('seats', 'attendee_ids')
    def _taken_seats(self):
        for r in self:
            if not r.seats:
                r.taken_seats = 0.0
            else:
                r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats
    


Field compute diatas berfungsi untuk menghitung persentase antara jumlah kursi yang disediakan dengan total peserta yang ada. Method yang digunakan berada pada attribute compute yaitu ‘_taken_seats’. Method itu mengandung decorator @api.depends(), artinya method akan selalu dijalankan ketika ada perubahan nilai pada 2 field terkait yaitu ‘seats’ dan ‘attendee_ids’. Penjelasan decorator penulis pernah sampaikan pada artikel ini.

Kemudian kita tampilkan field compute tersebut pada list view dan form view object training_sesi. Seperti berikut (perhatikan id xmlnya) :




	<record model="ir.ui.view" id="sesi_tree_view">
	    <field name="name">training.sesi.tree</field>
	    <field name="model">training.sesi</field>
	    <field name="arch" type="xml">
	        <tree string="Sesi List">
				<field name="name"/>
				<field name="course_id"/>
				<field name="start_date"/>
				<field name="duration"/>
				<field name="seats"/>
				<field name="instructor_id"/>
				<field name="taken_seats" widget="progressbar"/>     
	        </tree>
	    </field>
	</record>
	
	
		
	<record model="ir.ui.view" id="sesi_form_view">
		<field name="name">training.sesi.form</field>
		<field name="model">training.sesi</field>
		<field name="arch" type="xml">
			<form string="Sesi Form">
				<sheet>
					<group>
						<group string="Informasi">
							<field name="course_id"/>
							<field name="name"/>
							<field name="instructor_id"/>
						</group>
						<group string="Jadwal">
							<field name="start_date"/>
							<field name="duration"/>
							<field name="seats"/>
							<field name="taken_seats" widget="progressbar"/>							
						</group>
						<group string="Peserta" colspan="2">
							<field name="attendee_ids" nolabel="1"/>
						</group>						
					</group>
				</sheet>
			</form>
		</field>
	</record>
	


Hasilnya seperti foto berikut (perhatikan field ‘Kursi Terisi’) :

Ada banyak jenis widget yang odoo sediakan dan masing-masing widget memiliki tampilan yang berbeda-beda. Untuk menggunakannya kita bisa set pada attribut widget, diantaranya :


char
id
email
url
text
char_domain
date
datetime
selection
radio
reference
boolean
boolean_button
toggle_button
float
percentpie
integer
float_time
progressbar
image
binary
statusbar
monetary
priority
kanban_state_selection
many2many_tags
kanban_label_selection
handle
statinfo
timezone_mismatch
label_selection
ace

Selanjutnya kita akan tentukan nilai default pada field ‘start_date’ seperti contoh berikut :


class Sesi(models.Model):
    
    ...

    start_date = fields.Date(default=fields.Date.today)
    
    ...

Terakhir, saat kita membuka form Kursus, maka disana ada tabel Sesi. Untuk menambahkan sesi kita harus mengklik text “Add an item” sebagaimana semua tabel di odoo. Setelah kita klik, maka akan terbuka pop up form dari Sesi. Agar kita tidak perlu ada pop up dan cukup menambahkannya langsung pada table, maka kita gunakan attribut editable. Attribute editable memiliki value top dan bottom, silahkan mengupdate view xml seperti di bawah ini :



	<record model="ir.ui.view" id="kursus_form_view">
	    <field name="name">training.kursus.form</field>
	    <field name="model">training.kursus</field>
	    <field name="arch" type="xml">
	        <form string="Kursus Form">
	            <sheet>
	                <group>
	                    <field name="name"/>
	            		<field name="responsible_id"/>
	                </group>
	                <notebook>
	                    <page string="Keterangan">
	                        <field name="description"/>
	                    </page>
	                    <page string="Sesi">
							<field name="session_ids">
								<tree string="Daftar Sesi" editable="bottom">
									<field name="name"/>
									<field name="instructor_id"/>
								</tree>
								<form>
									<group string="Informasi">
										<field name="name"/>
										<field name="instructor_id"/>
									</group>
									<group string="Jadwal">
										<field name="start_date"/>
										<field name="duration"/>
										<field name="seats"/>
									</group>
								</form>
							</field>
						</page>
	                </notebook>
	            </sheet>
	        </form>
	    </field>
	</record>
	

Silahkan di restart + upgrade modul dan lihat perbedaannya. Klik disini mendownload modul yang dihasilkan.

Semoga bermanfaat, CMIIW …

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s