Anda di halaman 1dari 231

DASAR-DASAR OPENERP:

SISI TEKNIKAL DAN CONTOH KASUS


oleh:
Noprianto
Whisnu Budhysantika
Widoyo

"Beberapa kelebihan buku ini: ditulis oleh para programer dan praktisi yang bukan saja pernah
mengimplementasi tapi juga memodifikasi OpenERP, ditujukan tidak hanya untuk Windows tapi juga
Linux, dan diterbitkan secara independen dan dengan lisensi terbuka. Disarankan dibaca."
Steven Haryanto

"OpenERP merupakan produk open source yang mudah dikembangkan dan konsisten. Meski begitu
dukungannya cenderung komersil. Ini membuat developer pas-pasan seperti saya kesulitan
mempelajarinya. Kita beruntung Noprianto dkk bersedia membuat buku yang cukup rinci ini
dihadirkan tanpa dipungut biaya."
Owo Sugiana

Menemukan materi teknis yang ditulis dalam bahasa Indonesia bagaikan


mencari jarum di dalam jerami. Bukan karena orang Indonesia tidak ada
yang pakar dalam hal teknis ini tapi lebih karena tidak ada yang mau,
tidak sempat, atau tidak memiliki kemampuan menulis. Dan memang
menulis hal teknis dalam bahasa Indonesia memiliki tantangan
tersendiri. Penulisan buku OpenERP dengan model terbuka dan
sukarelawan ini patut diacungi jempol. Bagian studi kasus membantu
memberikan gambaran kepada pembaca hal apa yang bisa diselesaikan
menggunakan OpenERP. Bagi yang belum terbiasa dengan Python bisa mulai
dengan bagian lampiran Python Dasar.
Zaki Akhmad

Buku tersedia bebas di https://github.com/id-python/buku-openerp

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


TENTANG BUKU
DASAR-DASAR OPENERP: SISI TEKNIKAL DAN CONTOH KASUS
(c) 2014 Noprianto, Whisnu Budhysantika, Widoyo
Revisi: 0 (27 Agustus 2014, publikasi sendiri)
Buku ini dapat dikopi dan disebarluaskan secara bebas, baik dalam bentuk softcopy ataupun tercetak,
dengan beberapa catatan berikut:
Buku ini diharapkan dapat berguna, namun tidak menggaransi apapun.
Setiap halaman dalam buku ini merupakan satu kesatuan dan tidak terpisahkan.
Apabila mengutip sebagian dari buku ini, cantumkanlah setidaknya judul buku, pengarang dan
nomor revisi.
Softcopy buku (dalam format OpenDocument dan PDF) tersedia bebas di https://github.com/idpython/buku-openerp

MEREK DAGANG

Windows adalah merek dagang terdaftar dari Microsoft Corporation.


Python adalah merek dagang dari Python Software Foundation.
Linux adalah merek dagang terdaftar dari Linus Torvalds.
OpenERP adalah merek dagang dari OpenERP s.a.

KATA PENGANTAR
Pertama-tama, saya mengucapkan terima kasih kepada Whisnu Budhysantika dan Widoyo yang telah
bersedia sama-sama menulis buku ini. Juga terima kasih kepada Owo Sugiana, Steven Haryanto, dan
Zaki Akhmad yang telah bersedia memberikan pujian untuk buku ini.
Menulis buku, sebagai proyek komunitas, tanpa ada kejelasan akan diterbitkan, pastinya bukan
pekerjaan yang menarik :) Perlu komitmen, terutama ketika ditengah proses penulisan, semua penerbit
yang kami hubungi tidak tertarik. Kami memilih untuk terus menulis dan menyediakan bukunya secara
bebas!
Buku ini dipersembahkan untuk komunitas Python Indonesia (http://www.python.or.id)

Noprianto

1/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Daftar Isi
1. Memulai OpenERP................................................................................................................................6
1.1 Instalasi............................................................................................................................................7
Instalasi di Microsoft Windows........................................................................................................7
Instalasi di distribusi Linux Ubuntu.................................................................................................8
1.2 Bekerja dengan database...............................................................................................................11
Membuat database..........................................................................................................................11
Operasi lain.....................................................................................................................................11
1.3 Settings dan technical features......................................................................................................12
1.4 Modul Sales Management.............................................................................................................15
2. Dasar-Dasar Kustomisasi.....................................................................................................................19
2.1 Developer Mode............................................................................................................................19
2.2 Menambah dan menampilkan field...............................................................................................22
Manage Views................................................................................................................................22
Field baru........................................................................................................................................24
2.3 Menyembunyikan dan mengatur posisi field................................................................................26
2.4 Kelebihan dan kekurangan............................................................................................................27
Kelebihan........................................................................................................................................27
Kekurangan.....................................................................................................................................27
3. Dasar Pengembangan Modul OpenERP..............................................................................................28
3.1 Paket Python..................................................................................................................................28
3.2 Manifest __openerp__.py..............................................................................................................28
3.3 File-file dalam modul....................................................................................................................28
3.4 Lingkungan OpenERP...................................................................................................................29
3.5 Lokasi Modul................................................................................................................................30
3.6 Update daftar modul......................................................................................................................31
3.7 Mencari dari daftar modul.............................................................................................................31
3.8 Langkah berikut.............................................................................................................................31
4. Kasus: Perusahaan Rental Kendaraan..................................................................................................33
4.1 Pendahuluan..................................................................................................................................33
Periode............................................................................................................................................33
Tipe Penggunaan.............................................................................................................................33
4.2 Langkah implementasi..................................................................................................................34
Setup Identitas Perusahaan.............................................................................................................34
Memasang Modul...........................................................................................................................35
Terjemahan Bahasa Indonesia........................................................................................................35
Kode Rekening...............................................................................................................................35
Data Awal........................................................................................................................................37
Operasi............................................................................................................................................41
Laporan...........................................................................................................................................45
5. Model pada OpenERP..........................................................................................................................49
5.1 Hirarki class...................................................................................................................................49
5.2 orm.Model, osv.Model dan osv.osv...............................................................................................51
2/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


5.3 Atribut............................................................................................................................................52
5.4 Atribut: _columns..........................................................................................................................54
Nama field spesial...........................................................................................................................54
Class _column.................................................................................................................................54
Tipe field: boolean..........................................................................................................................55
Tipe field: integer............................................................................................................................55
Tipe field: reference........................................................................................................................55
Tipe field: char................................................................................................................................56
Tipe field: text.................................................................................................................................56
Tipe field: html...............................................................................................................................56
Tipe field: float...............................................................................................................................56
Tipe field: date................................................................................................................................57
Tipe field: datetime.........................................................................................................................57
Tipe field: binary............................................................................................................................57
Tipe field: selection........................................................................................................................58
Tipe field: many2one......................................................................................................................59
Tipe field: one2many......................................................................................................................59
Tipe field: many2many...................................................................................................................60
Tipe field: function.........................................................................................................................60
Tipe field: related............................................................................................................................61
Tipe field lain..................................................................................................................................61
5.5 Atribut: _constraints......................................................................................................................62
5.6 Model, tabel database dan field.....................................................................................................63
5.7 Method...........................................................................................................................................65
Bekerja dengan model lain.............................................................................................................67
5.8 Mengakses OpenERP tanpa server dijalankan..............................................................................68
5.9 Method: search..............................................................................................................................70
5.10 Method: read................................................................................................................................72
5.11 Method: write..............................................................................................................................73
5.12 Method: create.............................................................................................................................74
5.13 Method: unlink............................................................................................................................75
5.14 Program 5-1: menambah field.....................................................................................................76
5.15 Program 5-2: readonly dan nilai default......................................................................................79
5.16 Program 5-3: constraint...............................................................................................................81
5.17 Program 5-4: field functional......................................................................................................84
5.18 Program 5-5: method create/write...............................................................................................86
6. Dasar-dasar View.................................................................................................................................87
6.1 Kerangka.......................................................................................................................................87
6.2 Field pada model...........................................................................................................................89
6.3 Inheritance pada view....................................................................................................................90
6.4 Form: mengatur ulang posisi field.................................................................................................92
6.5 Form: menambah field..................................................................................................................94
6.6 Form: notebook dan group............................................................................................................97
6.7 Form: attrs dan atribut lain..........................................................................................................100

3/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


6.8 Form: on change..........................................................................................................................103
6.9 Form: on change (2)....................................................................................................................106
6.10 Tree: tambah/hapus field...........................................................................................................108
6.11 Menuitem dan editable tree.......................................................................................................110
7. Dasar-dasar Report.............................................................................................................................115
7.1 Definisi........................................................................................................................................115
7.2 Report dengan RML....................................................................................................................117
7.3 Kerangka RML............................................................................................................................118
7.4 Report pada model.......................................................................................................................119
7.5 Custom parser..............................................................................................................................122
7.6 Wizard.........................................................................................................................................127
8. Tip dan Trik........................................................................................................................................134
8.1 Pelajarilah source code OpenERP...............................................................................................134
8.2 Generate file konfigurasi.............................................................................................................136
8.3 Lebih dari satu lokasi addons......................................................................................................137
8.4 Pustaka notation dan notasi prefix/postfix..................................................................................138
8.5 Lisensi pada modul OpenERP.....................................................................................................142
8.6 Perubahan pada file python dalam modul...................................................................................144
8.7 Menampilkan pesan kesalahan....................................................................................................144
8.8 Format tanggal/waktu..................................................................................................................145
9. Web Service dengan XML-RPC........................................................................................................146
9.1 ERP dan sistem berjalan..............................................................................................................146
9.2 Membangun frontend sendiri......................................................................................................147
9.3 XML-RPC dan Python................................................................................................................148
9.4 Pustaka oerpapi............................................................................................................................149
OErpClient....................................................................................................................................149
OErpModel...................................................................................................................................150
OErpDb.........................................................................................................................................152
OErpReport...................................................................................................................................154
Exception......................................................................................................................................155
Memeriksa hasil login...................................................................................................................156
9.5 Program: pilih dan login ke database..........................................................................................157
9.6 Program: buat, update, baca, hapus.............................................................................................159
9.7 Program: melakukan pencarian...................................................................................................162
9.8 Program: laporan.........................................................................................................................166
9.9 Program: buat, ganti nama, kopi, hapus database.......................................................................169
9.10 Program: dump dan restore database.........................................................................................172
9.11 Menggunakan xmlrpclib............................................................................................................174
10. Lampiran: Python Dasar..................................................................................................................177
Tentang dokumen ini.........................................................................................................................177
10.1 Penulisan source code...............................................................................................................178
10.2 Sekilas tentang Python..............................................................................................................180
10.3 Interpreter Python (interaktif)...................................................................................................181
10.4 Script Python.............................................................................................................................182

4/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


10.5 Tipe builtin, collection dan operator..........................................................................................183
Collection......................................................................................................................................186
Operator........................................................................................................................................187
10.6 Kondisi......................................................................................................................................190
Sintaks if.......................................................................................................................................190
10.7 Perulangan.................................................................................................................................192
Sintaks for.....................................................................................................................................192
Sintaks while.................................................................................................................................192
Catatan..........................................................................................................................................193
10.8 Fungsi........................................................................................................................................194
Deklarasi fungsi............................................................................................................................194
Documentation String (docstring)................................................................................................194
Pemanggilan fungsi......................................................................................................................195
Variabel global..............................................................................................................................195
Argumen fungsi............................................................................................................................197
Argumen default...........................................................................................................................198
Argumen *arg (tuple)....................................................................................................................199
Argumen **arg (dictionary).........................................................................................................200
10.9 Class..........................................................................................................................................202
10.10 Modul-modul...........................................................................................................................212
Contoh modul...............................................................................................................................213
Search path....................................................................................................................................216
Compiled module..........................................................................................................................216
Nama module................................................................................................................................216
Package.........................................................................................................................................217
10.11 Exception.................................................................................................................................220
Try...except...finally......................................................................................................................220
Try...finally...................................................................................................................................223
Informasi exception......................................................................................................................223
Membangkitkan exception............................................................................................................224
10.12 File...........................................................................................................................................225
Membuka dan menutup file..........................................................................................................225
Membaca isi file...........................................................................................................................226
Menulis ke file..............................................................................................................................228
Statement with..............................................................................................................................229

5/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

1. Memulai OpenERP
Penulis: Whisnu Budhysantika

OpenERP (dulu bernama TinyERP, sekarang bernama Odoo) adalah sebuah perangkat lunak Enterprise
Resource Planning (ERP) atau perangkat lunak perencanaan sumber daya perusahaan yang dilisensikan
free/open source. OpenERP dikembangkan dengan bahasa pemrograman Python. Source code dan
informasi selengkapnya tentang OpenERP bisa didapatkan di website http://www.openerp.com.
Perangkat lunak perencanaan sumber daya perusahaan akan memberikan manfaat yang besar kepada
sebuah perusahaan dalam membantu mengelola sumber daya di sebuah perusahaan sehingga semua
sumber daya yang dimiliki dapat tercatat, terkontrol dan dapat dengan mudah diberdayakan.
Sebagaimana lazimnya sistem aplikasi modern, arsitektur sistem pada OpenERP menerapkan sistem
modular. Setiap adopsi terhadap kebutuhan baru dapat menghasilkan modul baru. Modul-modul
tersebut bisa diinstall bila dibutuhkan. Saat ini tersedia ribuan modul, termasuk yang datang bersama
OpenERP seperti:
CRM
Social Network
eInvoicing & Payments
Point of Sale
Project Management
Issue Tracker
Accounting and Finance
Sales Management
Warehouse Management
MRP
Purchase Management
Employee Directory
Timesheets
Leave Management
Expense Management
Assets Management
Payroll
Kesemua modul yang terinstall dirancang untuk dapat saling terhubung.

6/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

OpenERP mengembangkan jaringan partnership dengan berbagai perusahaan di seluruh dunia untuk
bersama-sama menjadi pelopor dalam pengembangan OpenERP serta menjadi ujung tombak customer
support kepada pengguna OpenERP.

1.1 Instalasi
Server OpenERP dapat dijalankan pada berbagai sistem operasi populer, dan relatif tidak sulit untuk
diinstal. Bahkan, pada sistem operasi Microsoft Windows, tersedia installer yang siap digunakan.
Sementara, untuk client, hanya dibutuhkan web browser.
Berbagai komponen OpenERP, termasuk database, bisa diinstal pada satu server yang sama, ataupun
dipisahkan ke beberapa server.
Installer ataupun source code OpenERP bisa didownload dari websitenya.

Instalasi di Microsoft Windows


Untuk menginstall OpenERP dan PostgreSQL, harus menggunakan user dengan hak Administrator.
Jika sudah pernah menginstall komponen OpenERP sebelumnya, maka disarankan untuk dilakukan
uninstall terlebih dahulu, sebab beberapa komponen dari instalasi sebelumnya dapat menghambat
proses instalasi baru. Pastikan bahwa semua komponen dari OpenERP dan PostgreSQL sebelumnya
terhapus.
7/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Klik ganti pada file installer untuk menginstall OpenERP dan Accept semua parameter default, seperti
pada contoh berikut.
1.
2.
3.
4.
5.

Pilih Bahasa English


Welcome Box
Licence Agreement
Pilih komponen yang akan diinstall (Pilih semua komponen)
Configure PostgreSQL Hostname: localhost, Port: 5432, Username: openpg, Password:
openpgpwd
6. Pilih Folder untuk lokasi instalasi
7. Install
8. Selesai
Setelah selesai proses instalasi, kita tidak perlu menjalankan server OpenERP secara manual, sebab
telah terinstall sebagai service.
Untuk menggunakan OpenERP, bukalah web browser dan ketikkanlah URL server OpenERP, gunakan
port 8069 (default), misal http://localhost: 8069
Beberapa catatan:
Bila tampilan dari http://localhost:8069 kosong, maka cobalah untuk start dan stop service
OpenERP dari Start All Program OpenERP Server.
Periksa kembali konfigurasi OpenERP yang umumnya tersimpan di C:\Program Files\OpenERP All
In One\openerp-server.conf. Bukalah filenya dan perhatikan dengan seksama terutama pada bagian
database (diawali dengan db_).
Pastikanlah server database PostgreSQL telah berjalan.
Apabila diperlukan, bukalah log OpenERP yang biasanya tersimpan di C:\Program Files\OpenERP
All In One\openerp-server.log

Instalasi di distribusi Linux Ubuntu


Cara pertama
Updatelah database paket sistem dengan perintah berikut:
sudo apt-get update
Kemudian, installah paket-paket berikut, termasuk server database (diketikkan sebagai satu baris
perintah):
sudo apt-get install postgresql postgresql-client pgadmin3 python-dateutil python-feedparser pythongdata python-ldap python-libxslt1 python-lxml python-mako python-openid python-psycopg2 pythonpybabel python-pychart python-pydot python-pyparsing python-reportlab python-simplejson python-

8/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


vatnumber python-vobject python-tz python-webdav python-werkzeug python-yaml python-xlwt
python-zsi python-setuptools python-unittest2 python-mock python-jinja2
Berikutnya, untuk OpenERP, kita punya pilihan untuk:

Menggunakan paket deb yang disediakan

Menggunakan source code

Apabila menggunakan paket deb, downloadlah paket deb dari


http://nightly.openerp.com/7.0/nightly/deb/ dan installlah paket tersebut:
sudo dpkg -i <file.deb>

Apabila menggunakan source code, ekstraklah arsip source code dan masuklah ke dalam direktori hasil
ekstrak.
Cara kedua
Tambahkanlah entri berikut ke /etc/apt/sources.list:
deb http://nightly.openerp.com/7.0/nightly/deb/ ./
Kemudian jalankan:
sudo apt-get update
sudo apt-get install openerp

Persiapan database
Buatlah sebuah user database (kita berikan hak untuk membuat database). Gantilah <user> dengan
nama user yang diinginkan.
sudo -u postgres createuser --pwprompt --createdb <user>
Pastikanlah pengaturan authentication (contoh: /etc/postgresql/9.3/main/pg_hba.conf) telah dilakukan
dengan baik.

9/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


File konfigurasi dan server
Apabila menjalankan dari source code, pertama-tama, kita akan buat file konfigurasi dan simpan
sebagai config.ini:
./openerp-server -s -c config.ini stop-after-init
Selanjutnya, editlah file config.ini, terutama untuk parameter koneksi database (diawali db_).
Server kemudian bisa dijalankan dengan perintah:
./openerp-server -c config.ini
Apabila menggunakan paket deb:
File konfigurasi terletak di /etc/openerp/openerp-server.conf
Service openerp dapat digunakan untuk start/stop server OpenERP.

10/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

1.2 Bekerja dengan database


Akseslah server OpenERP menggunakan web browser. Apabila server terinstall pada localhost,
gunakanlah URL http://localhost:8069

Membuat database
Untuk membuat database, akses bagian Manage Databases, pada bagian create isi nama database yang
kita inginkan, misal db_latihan, isi password user admin untuk database tersebut. Bagian Master
Password secara default akan terisi dengan admin. Untuk mengubahnya, masuk ke bagian Password.
Untuk menambahkan demo data, aktifkanlah pilihan Load demonstration data. Tunggulah proses yang
berlangsung dan setelah selesai, kita akan login otomatis sebagai user admin dan diarahkan ke halaman
settings, dimana kita bisa melihat modul-modul yang telah terinstall.
Jika kita mengaktifkan pilihan Load demonstration data, maka setelah kita menginstall modul, data
sampel akan disertakan. Ini umumnya kita lakukan ketika mempelajari OpenERP.

Operasi lain
Selain pembuatan database yang telah dibahas sebelumnya, di bagian Manage Databases, kita dapat
pula melakukan berbagai operasi berikut. Semuanya membutuhkan password master OpenERP.
Duplicate
11/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Membuat duplikat dari sebuah database. Informasi yang diperlukan:
Original database name, nama database yang akan diduplikasi.
New database name, nama database yang akan menjadi hasil proses duplikasi.
Drop
Menghapus database. Kita akan diminta untuk memilih nama database yang akan dihapus.
Backup
Membackup sebuah database. Kita akan diminta untuk memilih nama database yang akan dibackup.
Restore
Membuat database baru berdasarkan hasil backup yang tersedia sebelumnya. Informasi yang
diperlukan:
File, file backup
New database name, nama database baru yang akan dibuat
Password
Mengubah password master. Kita akan diminta untuk memasukkan informasi:
New master password, password master baru
Confirm new master password, konfirmasi password master baru

1.3 Settings dan technical features


Di bagian settings, dimana kita diarahkan ketika pertama kali login sebagai admin, setelah membuat
database, kita akan menemukan beberapa menu dasar berikut.

Modules
Apps
Updates
Installed Modules, daftar modul yang telah kita instal. Apabila kriteria installed pada search
dihapus, kita bisa mencari dari semua modul yang tersedia.
Users
Users, daftar user OpenERP
Translations
Load a Translation, memilih bahasa yang akan dipergunakan

12/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Apabila kita ingin melakukan pengaturan lebih lanjut, kita dapat mengaktifkan technical features untuk
user tertentu. Sebagai contoh, ketika masih login sebagai admin, di bagian Settings:
pilihlah Users Users
Pilihlah Administrator (admin) dari daftar user
Klik tombol Edit
Aktiflah pada tab Access Rights
Aktifkan pilihan Technical Features
Klik tombol Save

13/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Ketika kita melakukan reload halaman, maka menu lain akan tersedia pada Settings.

14/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

1.4 Modul Sales Management


Masih di Settings, pada bagian Modules Installed Modules, hapuslah kriteria installed pada kotak
pencarian. Daftar modul lengkap akan ditampilkan. Kliklah pada tombol Install di modul Sales
Management.
Setelah instalasi dilakukan, kita akan diminta untuk mengatur:
Accounting Package, pilih Custom
Company, pilih perusahaan

Berikutnya, kita dapat mengatur opsi Accounting:


Company, pilih perusahaan
Currency, mata uang. Kita bisa pilih IDR
Sale Tax, pajak pada penjualan
Purchase Tax, pajak pada pembelian
Untuk mengubah data perusahaan, kliklah logo perusahaan (Edit Company data).
Untuk bekerja dengan Sales Management, kita bisa klik pada link Sales di baris menu bagian atas
layar:
Sales
Customers, berisi data customer yang tercatat dalam database kita.
Quotations, berisi quotation yang tercatat dalam database kita.
Sales Orders, berisi sales order yang tercatat dalam database kita.
Products
Products, berisi data produk yang dimiliki.

15/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Untuk bekerja dengan invoice, kita bisa akses melalui link Invoicing di baris menu bagian atas layar:
Customers
Customer Invoices, berisi data invoice untuk customer yang tercatat dalam database kita.
Customer Refunds, berisi refund dari customer yang tercatat dalam database kita. Refund
adalah dokumen yang berisikan pengurangan sejumlah tagihan dalam invoice yang telah dibuat
untuk customer. Selain melalui bagian ini, refund juga bisa di-generate dari Customer Invoices.
Sales Receipts, berisi data Sales Receipts yang kita terima dari customer. Sales Receipts ini
diperlukan untuk pembuatan Customer Payments.
Customer Payments, berisi data pembayaran yang kita terima dari customer. Kita juga bisa
membuat data pembayaran dari Sales Receipts atau Customer Invoice yang statusnya masih
Open.
Customers, berisi data customer.
Suppliers
Supplier Invoices, berisi data invoice dari supplier yang tercatat dalam database kita.
Supplier Refunds, berisi refund supplier yang tercatat dalam database kita.
Purchase Receipts, berisi data Purchase Receipts yang kita terima dari supplier. Purchase
Receipts ini diperlukan untuk pembuatan data Supplier Payments.
Supplier Payments, berisi data pembayaran dari kita kepada para supplier. Kita juga bisa
membuat data pembayaran dari Purchase Receipts.
Suppliers, berisi data supplier. Dibeberapa sistem bagian ini disebut Master Vendor.

16/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Untuk bekerja dengan laporan, kita bisa akses melalui link Reporting di baris menu bagian atas layar:
Dashboards
My Dashboard, berisi berbagai laporan yang kita ingin tampilkan sesuai kebutuhan kita.
Berbagai laporan yang terlihat di bagian ini bisa selalu kita ubah-ubah dengan cara masuk ke
modul yang kita inginkan laporannya, klik bagian Graph View dan dari drop down menu di
bagian search, klik Add to Dashboard.
Sales, berisi dashboard mengenai laporan Sales. Secara default bagian ini berisi daftar
Quotation dan grafik Monthly Turnover.
Sales
Sales Analysis, berisi daftar Sales dari setiap personal yang bisa ditampilkan dalam format list
ataupun grafik.
Accounting
Invoices Analysis, berisi laporan analisis invoice.
Sales Receipts Analysis, berisi laporan analisis Sales Receipts.

17/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

18/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

2. Dasar-Dasar Kustomisasi
Penulis: Whisnu Budhysantika

2.1 Developer Mode


Developer mode adalah sebuah fasilitas built-in yang terdapat dalam OpenERP. Yang menjadi ciri
utama dari fasilitas ini adalah hadirnya drop down Debug View di samping sebuah nama model.

Untuk mengaktifkan fasilitas ini, bisa dengan cara mengakses menu About OpenERP (terdapat di drop
down menu user yang login), lalu klik link Activate the developer mode pada dialog yang ditampilkan.

19/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Salah satu fitur yang sangat berguna ketika developer mode diaktifkan adalah kita bisa mengetahui
nama dan informasi lain tentang suatu field, ketika kursor mouse diarahkan pada label suatu field.
Selain itu, ketika sedang aktif pada suatu view, kita akan mendapatkan berbagai fasilitas berikut dari
drop down Debug View (item-item berikut tersedia apabila relevan):
View Log (perm_read), menampilkan data:
ID, Identitas unik dari sebuah obyek
XML ID, file xml yang berkaitan dengan obyek.
Creation User, menampilkan data pembuat
Creation Date, menampilkan data tanggal pembuatan
Latest Modification By, menampilkan data pengubah
Latest Modification Date, menampilkan data tanggal pengubahan data
Toggle Form Layout Outline, menampilkan layout dari sebuah form.
Set Defaults, fasilitas untuk membuat value yang ada dalam formulir tersebut menjadi default value
untuk form sejenis. Saat kita memilih fungsi ini, maka akan terdapat form baru yang berisi:
Default, berisi Dropdown mengenai value yang berada dalam form tersebut, misal alamat email,
language, signature dan timezone tergantung pada jenis form-nya.
Opsi Only You dan All Users, bila dipilih Only You, maka default value tersebut hanya berlaku
untuk user yang saat ini sedang login saja. Bila dipilih All Users, maka berlaku untuk semua
user yang terdaftar dalam database tersebut.
JS Test, berfungsi untuk melakukan debugging terhadap seluruh modul yang ada dalam sebuah
database. Kita akan diminta untuk menginput data nama database, password untuk mengakses
database tersebut dan admin password-nya. Selanjutnya adalah proses pengecekan modul oleh
OpenERP dan setelah selesai akan terlihat hasilnya. Bila ditemukan error, maka akan ditandai
20/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

dengan warna merah dan bisa di-extend untuk melihat detailnya.


View Fields, berfungsi untuk menampilkan field-field apa saja yang dimiliki dalam model tersebut.
Fields View Get, berfungsi untuk menampilkan data layout/view field-field untuk model tersebut.
Manage Filters. Dalam setiap model OpenERP, kita bisa menambahkan filter dengan
mendefinisikan domain dan context-nya. Fasilitas Manage Filters dimaksudkan untuk melakukan
CRUD (Create Retrieve Update & Delete) terhadap filter-filter yang kita butuhkan.
Technical translation, bagian ini berfungsi untuk mendefinisikan translasi teknis dari Field, Object,
Report/Template ,View, Wizard Button, Wizard Field, Wizard View, XSL, Help, Code, Constraint,
SQL Constraint.
Manage Views, berfungsi untuk mengatur view dari model yang sedang dilihat, mengatur field apa
saja yang ditampilkan, mengubah field, menambahkan ataupun menghapus field yang sedang
ditampilkan.
Edit View, berfungsi untuk mengedit view.
Edit FormView, berfungsi untuk mengedit form view.
Edit SearchView, berfungsi untuk mengedit search view.
Edit Action, berfungsi untuk melakukan pengubahan pada action.
Edit Workflow, berfungsi untuk melakukan CRUD terhadap workflow.
Print Workflow, berfungsi untuk melakukan printing terhadap workflow.

21/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

2.2 Menambah dan menampilkan field


Untuk menambahkan field pada sebuah model, bisa dilakukan dengan beberapa cara, yaitu:
Dari Manage Views: Cara ini adalah cara yang sangat mudah dilakukan dan tidak memerlukan
pengetahuan mengenai pemrograman python. Dapat dilakukan dengan mengaktifkan Developer
Mode, kemudian dari Debug View pilih Manage Views.
Dengan mengubah database structure. Aktifkanlah terlebih dahulu technical features untuk user
yang diinginkan, kemudian aktiflah di Settings. Di bagian Technical, pilihlah Database Structure
Fields. Kita bisa gunakan tombol Create untuk membuat field baru.
Dengan membangun modul sendiri (dibahas mulai dari bab 3).

Manage Views
Saat kita membuka Manage Views, fasilitas ini akan langsung memberikan petunjuk di view mana
sekarang ini kita sedang berada (selected radio button), sebab secara default semua view yang berkaitan
akan ditampilkan. Kita tidak perlu memilih view yang lainnya (kecuali kita tahu). Kita tinggal klik
tombol edit.

22/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Semua field yang aktif, ditampilkan dalam format XML <field name=nama_field>. Untuk
menambahkan sebuah field baru, kita tinggal mengklik icon plus (+) yang terdapat dibagian kanan
setiap field. Dengan cara ini pula kita bisa memastikan field baru tersebut akan terlihat dibagian mana
dari tampilan.
Saat mengkilk icon plus (+), kita akan dihadapkan ke sebuah dialog yang meminta kita untuk
menginput data Node Type (pilih field) dan Position, selanjutnya klik tombol New Field untuk
membuat field baru ataupun memilih field yang telah dibuat sebelumnya untuk menambahkan field
pada view.

23/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Field baru
Pada dialog penambahan field baru, kita akan diminta untuk memberikan data:
Wajib diisi
Field name: adalah nama field di database. Untuk penamaan field custom, harus diawali dengan
x_.
Field Label, label yang akan terlihat oleh pengguna.
Field Type, tipe field (untuk selengkapnya, bacalah juga bab 5).
Model, nama model openerp, misal res.partner untuk partner.
Searchable, bila dipilih, maka akan disertakan dalam proses pencarian data.
Tidak wajib diisi:
Domain, python expression, contoh [(color=red)] yang menunjukkan kemungkinan kriteria
dari field.
Serialized Field, jika di set maka field ini tidak akan dibuatkan dalam struktur database tapi
hanya di buat dalam sparse struktur.
Required, bila dipilih, maka field ini akan menjadi field yang wajib diisi.
Read Only, bila dipilih, maka field ini akan menjadi field yang tidak bisa diubah isi defaultnya.
Translatable, bila dipilih, dapat diterjemahkan.

24/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

25/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

2.3 Menyembunyikan dan mengatur posisi field


Menggunakan Manage Views, untuk setiap field, kita bisa klik tombol minus (-) untuk
menyembunyikan field. Ketika kita klik pada tombol Remove, kita hanya menghapusnya dari view.
Lebih lanjut, selain tombol + dan -, berikut ada fungsi dari berbagai tombol lainnya:
Icon kertas dan pensil: untuk memodifikasi/mengubah properti sebuah field (dari sisi view):
Name, nama sebuah field.
String, label dari sebuah field
Required, bila dipilih, maka field tersebut wajib diisi.
Readonly, bila dipilih, maka isi field tersebut tidak bisa diubah.
Invisible, bila dipilih, maka field tersebut tidak akan terlihat (tersembunyi).
Domain, digunakan untuk keperluan filter seperti domain="[('partner_id','=',partner_id)]".
Context, parameter kontekstual, seperti bahasa.
Attrs, atribut sebuah field, lebih lanjut bacalah juga bab 6.
Eval, ekspresi kode python, untuk data non string.
Ref, referensi sebuah field.
On change, fungsi on change, lebih lanjut bacalah juga bab 6.
No Label, bila dipilih, maka label dari field tersebut tidak akan ditampilkan.
Completion, bila dipilih, maka saat field tersebut diisi, akan terdapat saran dalam pengisiannya.
Colspan, pendefinisian jumlah kolom yang ditempati field.
Widget, contoh dari widget adalah mail_thread dan many2many_tags_email. Widget akan
mendefiniskan action yang akan diambil bila field ini digunakan.
Groups, mendefiniskan tempat field tersebut akan berada.
Icon panah hijau mengarah ke atas: untuk pengaturan urutan tampilan field. Bila icon ini di klik
maka field tersebut akan naik ke urutan tampilan di atas dari sebelumnya.
Icon panah hijau mengarah ke bawah: untuk pengaturan urutan tampilan field. Bila icon ini di klik
maka field tersebut akan turun ke urutan tampilan di bawah dari sebelumnya.

26/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

2.4 Kelebihan dan kekurangan


Kelebihan
Proses kostumisasi OpenERP dengan menggunakan fasilitas yang disediakan oleh OpenERP yaitu
Developer Mode dan Technical Features akan membawa kita pada pengalaman kemudahan
memodifikasi sistem tanpa harus repot bekerja dengan kode Python.
Kemudahan ini menjadi keunggulan tersendiri dari OpenERP. Saat kita membangun sebuah sistem
informasi, baik itu pada skala kecil ataupun skala besar seperti ERP, dan kemudian kita harus
menerangkan sistem tersebut pada pengguna akhir, pertanyaan yang kemudian selalu muncul adalah
jika ingin menambahkan ini atau itu bagaimana?. Pertanyaan tersebut seringkali menjadi justifikasi
dari pengguna bahwa sebuah sistem itu sulit dan kurang user friendly saat mereka dihadapkan pada
kenyataan bahwa pengubahan harus melalui pengubahan pada pemrograman.
Tetapi ketika pengubahan itu dengan sangat mudah kita terangkan pada calon pengguna bahwa
pengubahan baik itu yang sifatnya penambahan, pengurangan dan lain-lain dapat dibuat dengan sangat
mudah hanya dengan beberapa kali klik saja, seringkali menjadi poin tersendiri dan dianggap bahwa
sistem yang kita buat sangat baik dan user friendly dari kacamata pengguna tersebut.
OpenERP didesain sedemikian rupa untuk bisa mengadopsi dengan baik setiap penambahan,
pengurangan ataupun perubahan terhadap sebuah field tanpa harus melakukan pemrograman.

Kekurangan
Apa yang kita lakukan sejauh ini berdampak pada satu database. Bayangkanlah apabila kita harus
melakukan sejumlah kustomisasi yang sama tersebut pada database lain, misal ketika instalasi ulang
dilakukan.
Apabila kita terjemahkan setiap apa yang kita lakukan dalam satu atau lebih modul, modul-modul yang
kita kembangkan tersebut dapat diinstall dan diuninstall setiap kali diperlukan. Sehingga kita bisa
bekerja dengan satu atau lebih database dengan lebih mudah.
Selain itu, terdapat kustomisasi yang lebih kompleks, yang hanya dapat dilakukan lewat pemrograman
dengan Python.

27/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

3. Dasar Pengembangan Modul OpenERP


Penulis: Whisnu Budhysantika / Noprianto

3.1 Paket Python


Sebuah modul OpenERP terdiri dari satu direktori dan juga merupakan sebuah paket Python yang
valid. Dan, oleh karenanya, file __init__.py harus tersedia.
File __init__.py bisa berupa file kosong, ataupun berisikan kode-kode inisialiasi. Di dalam bab-bab
berikut, dalam contoh modul, kita bisa melihat bahwa kode-kode inisialiasi tidak diperlukan apabila
kita tidak bekerja dengan kode Python, dan hanya fokus pada view, sebagai contoh. Sebaliknya, apabila
kita bekerja dengan model (misal: menambah field), maka __init__.py umumnya berisi statement
import untuk modul lain di dalam paket.

3.2 Manifest __openerp__.py


Supaya sebuah modul dikenal oleh OpenERP dan informasi lebih rinci tentang modul bisa disediakan,
maka kita perlu membuat sebuah file manifest, dengan nama file __openerp__.py, di dalam direktori
modul yang kita kembangkan.
File ini akan berisikan sebuah dictionary Python, dengan key berikut.
name: nama modul
version: versi modul
author: pengembang
license: lisensi modul (default AGPL-3). Bacalah juga bab 8 apabila diperlukan.
description: deskripsi apa yang dilakukan oleh modul
category: kategori modul
website: website modul (URL)
depends: daftar modul lain yang dibutuhkan
data: daftar file yang di-load (umumnya XML) pada saat modul diinstall atau diupdate
demo: daftar file tambahan yang di-load (umumnya XML) pada saat modul diinstall atau diupdate
dan flag demo aktif.

3.3 File-file dalam modul


Untuk bekerja dengan suatu model, umumnya kita tempatkan dalam sebuah modul Python tersendiri
(file .py). Modul tersebut kemudian kita import dari __init__.py.

28/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Untuk bekerja dengan view, dalam bentuk file XML, umumnya file-file XML ditempatkan di dalam
subdirektori view.
File-file yang diperlukan untuk report ataupun wizard umumnya ditempatkan pada subdirektori
tersendiri (report dan wizard sebagai contoh).

3.4 Lingkungan OpenERP


Apabila kita melihat pada source code OpenERP:
$ ls -1 --group-directories-first
debian
doc
install
openerp
openerp.egg-info
win32
LICENSE
MANIFEST.in
openerp-server
PKG-INFO
README
setup.cfg
setup.nsi
setup.py
setup_rpm.sh

Kita bisa melihat satu direktori openerp. Ini merupakan sebuah paket Python:
$ ls -1 --group-directories-first openerp
addons
cli
conf
modules
osv
report
service
tests
tools
workflow
exceptions.py
import_xml.rng
__init__.py
loglevels.py
netsvc.py
PKG-INFO
pooler.py
release.py
sql_db.py

29/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Kita akan banyak bekerja dengan osv:
$ ls -1 --group-directories-first openerp/osv/
expression.py
fields.py
__init__.py
orm.py
osv.py
query.py

Terutama pada modul orm.py dan fields.py:


$ file openerp/osv/orm.py
openerp/osv/orm.py: Python script, ASCII text executable
$ file openerp/osv/fields.py
openerp/osv/fields.py: Python script, UTF-8 Unicode text executable

Apabila kita berada dalam direktori source code OpenERP (root), kita bisa import orm.py dan fields.py
dengan cara berikut:
>>> from openerp.osv import orm, fields
>>> orm
<module 'openerp.osv.orm' from 'openerp/osv/orm.py'>
>>> fields
<module 'openerp.osv.fields' from 'openerp/osv/fields.py'>
>>>

Namun, apabila kita berada di luar source code, maka environment variabel PYTHONPATH perlu diset terlebih dahulu, pada saat kita ingin bekerja dengan nyaman menggunakan IDE (yang mendukung).
Kita tidak perlu lakukan ini pada level modul ketika instalasi dilakukan.

3.5 Lokasi Modul


Modul yang kita kembangkan perlu ditempatkan pada direktori yang dikenal oleh OpenERP, sebagai
direktori addons. Pada tree source code OpenERP, ini adalah:
$ file openerp/addons/
openerp/addons/: directory
$ ls -1 openerp/addons/ | head -n10
account
account_accountant
account_analytic_analysis
account_analytic_default
account_analytic_plans
account_anglo_saxon
account_asset
account_bank_statement_extensions

30/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


account_budget
account_cancel

Kita bisa kopikan modul yang kita kembangkan ke dalam direktori addons yang dikenal, apabila
memiliki hak tulis, atau kita bisa gunakan direktori lain. Direktori lain tersebut kemudian perlu
diinformasikan ke server OpenERP. Bacalah juga bab 8 apabila diperlukan.

3.6 Update daftar modul


Apabila diperlukan, pada saat kita menambahkan modul baru di file sistem, kita mungkin perlu
memberitahu server OpenERP bahwa ada modul baru yang ditambahkan.
Untuk keperluan tersebut, pertama-tama, aktifkanlah terlebih dahulu Technical features untuk user
admin dan:
Aktiflah di menu Settings
Klik Modules Update Modules List
Sebuah dialog akan ditampilkan, kliklah pada tombol Update

3.7 Mencari dari daftar modul


Apabila modul kita dikenal, maka kita bisa mencari dan melihat informasi detilnya. Di menu Settings,
pilihlah Modules Installed Modules. Pada kotak pencarian, hapuslah kriteria installed dan isikan
dengan nama modul kita. Apabila berhasil, modul akan tampil dan kita bisa klik install untuk
melakukan instalasi.
Apabila modul kita tidak dikenal:
Pastikan kita telah tempatkan pada direktori addons yang dikenal oleh OpenERP. Apabila
menempatkan pada direktori lain, pastikan kita sudah melakukan konfigurasi yang tepat.
Pastikan modul kita merupakan paket Python yang valid. Dengan pengaturan PYTHONPATH yang
tepat, Anda bisa coba lakukan import.
Pastikan manifest __openerp__.py telah benar.
Pastikan tidak ada sintaks yang salah sebagai sebuah modul Python.
Apabila diperlukan, lakukanlah update daftar modul.

3.8 Langkah berikut

Sebuah IDE yang nyaman sangat disarankan. Pilihlah IDE favorit Anda, dan daftarkanlah
PYTHONPATH ataupun hal serupa pada IDE Anda. Apabila didukung, kita bisa memanfaatkan
fasilitas code completion, sebagai contoh.
Mulailah dengan mengembangkan satu modul sederhana, yang menambahkan satu field pada satu

31/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

model. Kita bisa tampilkan field tersebut lewat UI supaya modul kita cukup sederhana.
Pastikan modul dikenal oleh OpenERP. Cobalah untuk install dan pastikan tidak ada pesan
kesalahan.
Apabila modul Anda menambahkan field pada model tertentu, maka Anda bisa juga melihatnya ke
dalam tabel database. Gunakanlah client PostgreSQL yang nyaman, seperti pgAdmin III.

Contoh modul buku_contoh.


__init__.py
from . import buku_contoh

__openerp__.py
{
'name': 'Contoh',
'version': '1.0',
'author': 'noprianto',
'description': 'Contoh modul sederhana',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': [],
}

buku_contoh.py
from openerp.osv import orm, fields
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
_columns = {
'buku_contoh': fields.char('Contoh field', size=20)
}

Pada contoh tersebut, kita akan menambahkan satu field, tapi tidak menampilkan dalam view. Ketika
modul sukses diinstall, tidak ada perubahan apapun yang ditampilkan pada model res.partner. Padahal,
sesungguhnya, sebuah field telah ditambahkan. Cobalah untuk menampilkan field buku_contoh dengan
Manage Views.
Untuk informasi tentang model, kita akan membahasnya di bab 5.

32/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

4. Kasus: Perusahaan Rental Kendaraan


Penulis: Widoyo

4.1 Pendahuluan
Sebuah perusahaan persewaan kendaraan, melayani sewa kendaraan:
1. Dengan sopir
2. Tanpa sopir

Periode
1. Harian
2. Mingguan
3. Bulanan

Tipe Penggunaan
1. Pribadi / keluarga
2. Dinas

Perawatan kendaraan menjadi tanggung jawab pemilik persewaan, terdiri dari:


1. Ganti oli
2. Ban
3. Service rutin

33/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

4.2 Langkah implementasi


Pastikanlah server OpenERP telah terinstall. Kemudian, buatlah sebuah database dengan nama
majulancar.

Setup Identitas Perusahaan


Bagian ini merupakan hal pokok, informasi identitas perusahaan, salah satunya untuk tampilan laporanlaporan yang nanti akan dihasilkan.
OpenERP mendukung sistem banyak perusahaan, namun dalam kasus ini hanya dicontohkan untuk satu
perusahaan.
Untuk melakukan ini, klik menu Settings Companies Companies

Pada setup perusahaan ini dibagi dalam beberapa bagian:


General Information: Berisi informasi umum perusahaan seperti nama, alamat, telepon, dan lainlain. Untuk rekening bank, bisa lebih dari satu.
Configuration: Berisi mata uang dan masalah logistik.
Overdue Payments: Berisi template untuk pelanggan bila terjadi keterlambatan membayar tagihan.

34/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Setelah selesai diberikan informasi perusahaan, kita dapat klik pada tombol Preview Header/Footer
untuk melihat header/footer.

Memasang Modul
Lakukanlah instalasi untuk modul-modul berikut:
Fleet Management
Point of Sale
eInvoicing & Payments (akan terinstall dengan sendirinya sebagai dependency)

Terjemahan Bahasa Indonesia


Kita dapat pula menggunakan terjemahan ke Bahasa Indonesia, dengan cara memilih menu Settings
Translations Load a translation, kemudian pilihlah Indonesian / Bahasa Indonesia.
Setelah itu, untuk setiap user, masuklah ke pengaturan Preference (drop down sisi kanan atas layar, klik
pada nama user), kemudian ubahlah Language ke Indonesian / Bahasa Indonesia.

Kode Rekening
Untuk mencatat semua transaksi agar dapat langsung masuk ke dalam catatan akuntansi (jurnal), perlu
disiapkan kode rekening-kode rekening (Chart of Account COA) yang nanti akan dipergunakan.
Untuk melakukan hal ini, pertama aktifkan Full accounting features, melalui menu Settings
Configuration Akuntansi Full accounting features: journals, legal statements, chart of accounts,
etc.
Lalu untuk mendapatkan daftar kode rekening, klik menu Akuntansi Configuration Akun
Templates Akun Account Templates.

35/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

36/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Data Awal
Data awal di sini dimaksudkan sebagai data-data dasar yang menjadi acuan data lain pada saat
pengoperasian. Data di sini pada saat berjalan juga masih tetap bisa dilakukan perbaikan, misalnya
ditambah, dihapus, atau diubah.

Beberapa data awal yang perlu untuk diisikan adalah:


1. Layanan persewaan, termasuk harga
2. Kendaraan yang dimiliki
3. Pelanggan yang telah pernah menggunakan jasa
Layanan Persewaan
Data ini adalah item-item yang nanti dijual. Mengikuti dari contoh kasus di atas, maka perlu disiapkan
penjelasan dari layanan yang akan dijual, antara lain:
1. Dengan atau tidak dengan sopir
2. Waktu sewa: harian (setengah hari dan sehari penuh), mingguan, dan bulanan
3. Keluarga atau dinas
Untuk menambahkan produk jual, klik pada menu POS Produk Produk, kemudian klik tombol
Create.

37/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Setiap produk perlu untuk dihubungkan dengan kode akun.

Kendaraan
Kendaraan perlu dicatat ke dalam sistem sebagai bagian dari aset. Administrasi kendaraan ini dilakukan
dari menu Fleet. Beberapa data yang perlu diadministrasi antara lain:
1. Kendaraan
2. Service, baik berkala maupun yang berbasis kejadian
3. Bahan bakar, yaitu pencatatan penggunaan bahan bakar
4. Biaya lain
5. Kontrak, misalnya bila kendaaraan disewa dalam jangka waktu yang lama atau berbasis kontrak
Untuk menambah kendaraan, klik menu Fleet Vehicle Vehicle, kemudian klik tombol Create.

38/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Kendaraan yang telah ditambahkan akan tampil pada daftar kendaraan.

39/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Pelanggan
Pelanggan ini adalah pilihan, artinya tidak wajib ditambahkan. Namun lebih baik ditambahkan, hal ini
akan memberi nilai tambah sistem agar dapat diketahui loyalitas pelanggan. Selain itu juga berguna
untuk menjaga hubungan agar pelanggan tetap loyal dan perbaikan layanan.
Pelanggan dapat berupa perorangan maupun perusahaan. Data pelanggan perlu dihubungkan dengan
kode rekening yang telah disiapkan sebelumnya.
Data pelanggan dapat dilihat dari menu Sales Sales Customers.

40/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Operasi
Setelah data-data disiapkan, sistem dapat dioperasikan untuk mencatat transaksi-transaksi yang terjadi.
Beberapa transaksi yang mungkin terjadi pada sistem antara lain:
1. Pelanggan melakukan sewa kendaraan
2. Kendaraan dilakukan perbaikan
3. Laporan keuangan
Pelayanan Sewa Kendaraan
Ada beberapa langkah untuk hingga menerima pembayaran, yaitu:
1. Membuat penawaran
2. Konfirmasi penjualan
3. Membuat tagihan / invoice
4. Terima pembayaran
Pencatatan sewa kendaraan dapat dimulai dari membuat penawaran yang dilakukan melalui menu Sales
Sales Order Penjualan dan klik tombol Create.

41/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Setelah selesai mengisi data-data, lalu klik tombol Confirm Sale. Setelah ini, maka kita bisa membuat
tagihan / faktur. Setelah Buat Faktur, lalu View Invoice dan klik tombol Validasi, maka faktur sudah
final yang dapat dicetak untuk pelanggan sebagai bahan tagihan.

42/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Untuk mencatat penerimaan pembayaran, klik tombol Register Payment. Pada dialog yang ditampilkan,
isikan pembayaran dan klik tombol Pay.

43/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Hal ini akan membuat status dari penjualan ini sudah terbayar.

Pencatatan Biaya Kendaraan

44/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Laporan
Ada berbagai laporan keuangan dapat dihasilkan dari openERP. Berikut ini beberapa screenshot yang
mungkin berkaitan dengan Laporan.
Laporan dapat diakses dari menu Reporting.
Dashboard Laporan

45/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Laporan Biaya Kendaraan (Fleet Cost)

46/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Laporan Analisa Penjualan

Laporan Akuntansi

47/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

48/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5. Model pada OpenERP


Penulis: Noprianto
Di bab sebelumnya, kita telah membahas dasar-dasar pengembangan modul OpenERP. Kita
mengetahui bahwa kita perlu membuat manifest dan informasi apa saja yang perlu disertakan ke dalam
file manifest suatu modul agar dapat dikenal oleh OpenERP. Kita juga membuat class, yang diturunkan
dari orm.Model dan kemudian bekerja dengan model yang telah disediakan. Kita mengetahui bahwa
kita dapat menambahkan field dengan tipe tertentu.
Di bab ini, kita akan membahas lebih lanjut tentang class orm.Model tersebut. Termasuk diantaranya
sebagian dari atribut dan method yang telah disediakan.

5.1 Hirarki class


Ketika kita bekerja dengan suatu business object, kita menurunkan dari class orm.Model. Pada source
code OpenERP, class ini didefinisikan pada openerp/osv/orm.py. Class ini merupakan turunan dari
BaseModel, yang juga didefinisikan pada file yang sama. Lebih lanjut, class BaseModel merupakan
base class untuk model pada OpenERP.
|
|
|
|

Method resolution order:


Model
BaseModel
__builtin__.object

Untuk bekerja dengan class ini, kita melakukan import dengan cara:
>>> from openerp.osv import orm

Atau, ketika ingin menambahkan field:


>>> from openerp.osv import orm, fields

Apa yang kita lakukan pada contoh terakhir adalah mengimport modul orm dan fields dari package
openerp.osv. Sebagai catatan, modul fields mendefinisikan class-class tipe field yang didukung oleh
OpenERP.
Dengan menurunkan dari class Model ini, kita dapat menggunakan dan/atau mengoverride sejumlah
atribut dan method yang telah disediakan.

Dengan komentar tidak disertakan, ini adalah definisi seutuhnya dari class Model.

49/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

class Model(BaseModel):
_auto = True
_register = False
_transient = False

50/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.2 orm.Model, osv.Model dan osv.osv


Pada berbagai modul yang kita gunakan (baik yang disertakan ataupun dari pihak ketiga), kita akan
menemukan class yang diturunkan dari osv.osv. Pada dokumentasi tertentu, kita juga akan menjumpai
osv.Model.
Apabila kita mencermati file openerp/osv/osv.py, kita bisa melihat bahwa osv.osv digunakan untuk
backward compatibility:
# deprecated - for backward compatibility.
osv = Model
osv_memory = TransientModel
osv_abstract = AbstractModel # ;-)

Lebih lanjut, modul orm diimport oleh modul osv:


import orm

from openerp.osv.orm import MetaModel, Model, TransientModel, AbstractModel

Dengan cara demikian, kita bisa menggunakan osv.osv dan osv.Model untuk backward compatibility.
Di prompt interaktif Python:
>>> from openerp.osv import osv
>>> osv.osv
<class 'openerp.osv.orm.Model'>
>>> osv.Model
<class 'openerp.osv.orm.Model'>
>>>
>>>
>>> from openerp.osv import orm
>>> orm.Model
<class 'openerp.osv.orm.Model'>
>>>
>>>

Walaupun kita tetap bisa menggunakan osv.osv, untuk kode baru yang ditujukan untuk dijalankan pada
OpenERP versi baru, kita akan menggunakan orm.Model.

51/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.3 Atribut
Class BaseModel memiliki sejumlah atribut yang memiliki peranan/arti tertentu dalam OpenERP. Dan,
class Model, sebagai turunan, hanya mendefinisikan ulang beberapa dari atribut tersebut. Class yang
kita bangun, sebagai turunan dari Model, juga melakukan hal yang lebih kurang sama.
Dalam contoh yang akan kita bahas, dimana kita menambah field pada model tertentu, apa yang kita
lakukan adalah:
Membuat sebuah class baru (menurunkan dari Model)
Mendefinisikan ulang beberapa atribut seperti _name, _inherit dan _columns.
Tanpa kita melakukan lebih jauh lagi, field secara otomatis akan ditambahkan.
Berikut adalah sejumlah atribut yang disediakan oleh Model.
Atribut
Default

Catatan

_auto

True

_register

False

_name

None

[Wajib] merupakan nama business object


dalam notasi titik (misal: res.partner)

_columns

{}

berisikan nama field dan tipenya

_constraints

[]

List dari tuple (nama_fungsi, pesan_kesalahan,


fields) untuk memastikan input adalah valid.

_custom

False

_defaults

{}

Berisikan nilai default, dengan key adalah


nama kolom. Bisa berupa literal ataupun fungsi

_rec_name

None

Field alternatif untuk digunakan sebagai name

_parent_name

'parent_id'

_parent_store

False

_parent_order

False

_date_name

'date'

_order

'id'

_sequence

None

_description

None

_needaction

False

_group_by_full

{}

Apabila True, maka tabel akan dibuat secara


otomatis.

Field untuk keperluan sort

52/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Atribut
_transient

Default

Catatan

False

_inherit

[Pada inheritance tradisional] merupakan


_name dari business object parent (wajib,
apabila kita menurunkan).

_inherits

{}

_inherit_fields

{}

_all_columns

{}

_table

None

_invalids

set()

_log_access

Apabila
tidak Apabila True, maka 4 field akan dibuat
ditentukan,
maka otomatis: create_uid, create_date, write_uid,
nilai
diambil write_date, untuk keperluan log.
berdasarkan _auto,
dengan
default
adalah True

_log_create

False

Nama tabel database. Secara default adalah


_name dengan titik diganti dengan underscore.

_sql

SQL code untuk membuat table/view apabila


_auto adalah False.

_sql_constraints

[]

_protected

['read', 'write',
'create',
'default_get',
'perm_read',
'unlink',
'fields_get',
'fields_view_get'
, 'search',
'name_get',
'distinct_field_g
et',
'name_search',
'copy',
'import_data',
'search_count',
'exists']

CONCURRENCY_CHECK_FIELD

'__last_update'

List dari tuple untuk menentukan SQL


constraint

Beberapa atribut akan dibahas secara khusus pada bagian-bagian berikut.


53/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.4 Atribut: _columns


Sebagaimana dibahas sebelumnya, atribut _columns digunakan untuk menentukan field dan tipenya,
dalam sebuah dictionary.
Apabila kita menurunkan dari business object yang ada, dengan tujuan untuk menambah field, maka
kita cukup mendefinisikan field-field yang ingin kita tambahkan saja.
Mari kita ingat kembali ketika melakukan import modul orm dan fields:
>>> from openerp.osv import orm, fields

Modul fields mendefinisikan class-class field yang didukung oleh OpenERP. Contoh output dari dir()
module fields:
>>> dir(fields)
['Binary', 'DT', 'SUPERUSER_ID', '_', '__builtin__', '__builtins__', '__doc__',
'__file__', '__name__', '__package__', '_column', '_logger', '_symbol_set',
'_symbol_set_char', 'base64', 'binary', 'boolean', 'char', 'column_info', 'date',
'datetime', 'dummy', 'field_to_dict', 'float', 'float_repr', 'float_round',
'function', 'get_nice_size', 'html', 'html_sanitize', 'integer',
'invalid_xml_low_bytes', 'logging', 'many2many', 'many2one', 'one2many', 'openerp',
'property', 'pytz', 're', 'reference', 'related', 'sanitize_binary_value',
'selection', 'serialized', 'simplejson', 'sparse', 'text', 'tools', 'xmlrpclib']
>>>

Nama field spesial


Terdapat beberapa nama field spesial yang tidak dapat digunakan (beberapa akan dibuat secara
otomatis oleh sistem): id, name, active, sequence, state, parent_id, parent_left, parent_right,
create_date, create_uid, write_date, write_uid.

Class _column
Modul fields mendefinisikan sebuah class dengan nama _column, yang merupakan base class untuk
semua tipe field. Berikut adalah atribut yang didefinisikan:
>>> from openerp.osv import orm, fields
>>> c = fields._column()
>>> dir(c)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', '_as_display_name', '_auto_join',
'_classic_read', '_classic_write', '_context', '_deprecated', '_domain', '_multi',
'_obj', '_prefetch', '_properties', '_symbol_c', '_symbol_f', '_symbol_get',

54/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


'_symbol_set', '_type', 'as_display_name', 'change_default', 'deprecated', 'get',
'group_operator', 'groups', 'help', 'manual', 'ondelete', 'priority', 'read',
'readonly', 'required', 'restart', 'search', 'select', 'selectable', 'set', 'size',
'states', 'string', 'translate', 'view_load', 'write']
>>>

Beberapa dari atribut tersebut memiliki arti khusus, sebagai contoh:


string: label field
required: harus diisi
readonly: hanya dapat dibaca
help: tooltip help

Tipe field: boolean


Merupakan tipe dasar, digunakan untuk benar/salah.
Class dan constructor:
class boolean(_column)
| __init__(self, string='unknown', required=False, **args)

Contoh (cuplikan dari program 5-1):


'buku_field_4': fields.boolean('Buku Field 4'),

Tipe field: integer


Merupakan tipe dasar, digunakan untuk integer.
Class dan constructor:
class integer(_column)
| __init__(self, string='unknown', required=False, **args)

Contoh (cuplikan dari program 5-1):


'buku_field_3': fields.integer('Buku Field 3', size=10),

Tipe field: reference


Merupakan tipe dasar. Berisikan dynamic relationship ke object lain.
Class dan constructor:
55/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

class reference(_column)
| __init__(self, string, selection, size, **args)

Tipe field: char


Merupakan tipe dasar, digunakan untuk menampung string (panjang dibatasi).
Class dan constructor:
class char(_column)
| __init__(self, string='unknown', size=None, **args)
Catatan: size, ketika diberikan, akan menentukan maksimal panjang field.
Contoh (cuplikan dari program 5-1):
'buku_field_1': fields.char('Buku Field 1', size=20,
required=True,
help='Contoh help'),

Tipe field: text


Merupakan tipe dasar, digunakan untuk menampung teks.
Class:
class text(_column)

Tipe field: html


Merupakan tipe dasar. Merupakan turunan dari text.
Class:
class html(text)

Tipe field: float


Merupakan tipe dasar, digunakan untuk menampung bilangan floating point.

56/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Class dan constructor:


class float(_column)
| __init__(self, string='unknown', digits=None, digits_compute=None, required=False, **args)
Catatan: digits diberikan dalam format (precision, scale). Gunakanlah selalu apabila bekerja dengan
nilai nominal uang.
Contoh (cuplikan dari program 5-1):
'buku_field_2': fields.float('Buku Field 2', digits=(4, 2)),

Tipe field: date


Merupakan tipe dasar, digunakan untuk menampung tanggal.
Class:
class date(_column)
Contoh (cuplikan dari program 5-1):
'buku_field_5': fields.date('Buku Field 5'),

Tipe field: datetime


Merupakan tipe dasar, digunakan untuk menampung tanggal/waktu.
Class:
class datetime(_column)
Contoh (cuplikan dari program 5-1):
'buku_field_6': fields.datetime('Buku Field 6'),

Tipe field: binary


Merupakan tipe dasar. Sesuai konvensi legacy OpenERP adalah untuk transfer/menyimpan data biner
sebagai string dalam encoding base64. Sebagai contoh adalah isi file binary.
57/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Class dan constructor:


class binary(_column)
| __init__(self, string='unknown', filters=None, **args)

Tipe field: selection


Merupakan tipe dasar, digunakan untuk pilihan.
Class dan constructor:
class selection(_column)
| __init__(self, selection, string='unknown', **args)
Catatan: selection diberikan dalam list dari tuple (key, label) ataupun dengan menggunakan fungsi.
Contoh (cuplikan dari program 5-1):

SELECTION_1 = [
('pilihan1', 'Pilihan 1'),
('pilihan2', 'Pilihan 2'),
('pilihan3', 'Pilihan 3'),
]
SELECTION_2 = [
('pilihan4', 'Pilihan 4'),
('pilihan5', 'Pilihan 5'),
('pilihan6', 'Pilihan 6'),
('pilihan7', 'Pilihan 7'),
('pilihan8', 'Pilihan 8'),
('pilihan9', 'Pilihan 9'),
('pilihan10', 'Pilihan 10'),
]

class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
def _get_selection_2(self, cr, uid, context=None):
return SELECTION_2

58/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

'buku_field_7': fields.selection(SELECTION_1, 'Buku Field 7'),


'buku_field_8': fields.selection(_get_selection_2, 'Buku Field 8'),

Tipe field: many2one


Merupakan tipe relasional, digunakan untuk relasi many to one (banyak ke satu). Penerapannya adalah
umumnya pada relasi ke object parent (menggunakan foreign key).
Class dan constructor:
class many2one(_column)
| __init__(self, obj, string='unknown', auto_join=False, **args)
Salah satu contoh tipe field ini yang umum ditemukan pada OpenERP adalah model sale.order.line,
dimana field order_id (many) berhubungan dengan model sale.order.
Contoh (cuplikan dari openerp/addons/sale/sale.py):
'order_id':
fields.many2one('sale.order',
ondelete='cascade',
select=True,
[('readonly',False)]}),

'Order
Reference',
required=True,
readonly=True,
states={'draft':

Tipe field: one2many


Merupakan tipe relasional, digunakan untuk relasi one to many (satu ke banyak). Merupakan kebalikan
dari many2one.
Class dan constructor:
class one2many(_column)
| __init__(self, obj, fields_id, string='unknown', limit=None, auto_join=False, **args)
Salah satu contoh tipe field ini yang umum ditemukan pada OpenERP adalah model sale.order, dimana
field order_line (one) berhubungan dengan model sale.order.line (pada field order_id).
Contoh (cuplikan dari openerp/addons/sale/sale.py):
59/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

'order_line':
readonly=True,
False)]}),

fields.one2many('sale.order.line',
'order_id',
'Order
Lines',
states={'draft': [('readonly', False)], 'sent': [('readonly',

Tipe field: many2many


Merupakan tipe relasional, digunakan untuk relasi many to many (banyak ke banyak). Merupakan
multiple relationship dua arah antara object.
Class dan constructor:
class many2many(_column)
| __init__(self, obj, rel=None, id1=None, id2=None, string='unknown', limit=None, **args)
Salah satu contoh tipe field ini yang umum ditemukan pada OpenERP adalah hubungan antara model
res.partner dengan model res.partner.category.
Contoh (cuplikan dari openerp/addons/base/res/res_partner.py):
'category_id':
fields.many2many('res.partner.category',
id2='category_id', string='Tags'),

id1='partner_id',

Tipe field: function


Merupakan tipe functional, yang mensimulasikan field sesungguhnya, melalui proses komputasi.
Class dan constructor:
class function(_column)
| __init__(self, fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type='float', fnct_search=None,
obj=None, store=False, multi=False, **args)
Untuk argumen fnct, fungsi harus didefinisikan sebagai berikut:
fnct(model, cr, uid, ids, field_name(s), arg, context)
Kita akan membahas contoh sederhana pada program 5-4. Cuplikan kode:

def _function_test(self, cr, uid, ids, field, arg, context=None):

60/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


res = {}
for i in ids:
res[i] = random.random()
return res
_columns = {
'buku_field_12': fields.function(_function_test, type='float')
}

Untuk contoh tersebut, field buku_field_12 tidak disimpan pada tabel database.

Tipe field: related


Merupakan tipe related, diturunkan dari function, yang merujuk pada data di dalam field lain untuk
record aktif.
Class dan constructor:
class related(function)
| __init__(self, *arg, **args)

Salah satu contoh tipe field ini yang dapat ditemukan pada OpenERP adalah field country_id dan
country pada res.partner.
Contoh (cuplikan dari openerp/addons/base/res/res_partner.py):
'country_id': fields.many2one('res.country', 'Country'),
'country': fields.related('country_id', type='many2one', relation='res.country',
string='Country',
deprecated="This field will be removed as of
OpenERP 7.1, use country_id instead"),

Tipe field lain


Beberapa tipe field berikut didefinisikan di dalam modul fields:
sparse(function)
dummy(function)
serialized(_column)
property(function)
61/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.5 Atribut: _constraints


Sebagaimana dibahas sebelumnya, atribut _constraints dapat digunakan untuk membantu memastikan
input adalah valid.
Atribut ini didefinisikan dalam bentuk sebuah list dari tuple (nama_fungsi, pesan_kesalahan, fields).
Mari kita lihat cuplikan dari program 5-3 berikut.
Kita memiliki sebuah field dengan nama buku_field_11:
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
_columns = {
'buku_field_11': fields.char('Buku Field 11', size=20,
required=True),
}

Dan, kita ingin agar isi field tersebut, yang bertipe char, harus memiliki panjang minimal tiga karakter.
Kita dapat definisikan _constraints dan fungsi untuk memeriksa, sebagai berikut:
def _check_field_11(self, cr, uid, ids, context=None):
for i in self.browse(cr, uid, ids, context=context):
if len(i.buku_field_11) >= 3:
return True
return False
_constraints = (
[_check_field_11, 'Panjang harus minimal 3 karakter',
['buku_field_11']],
)

Untuk nama_fungsi, kita gunakan _check_field_11.


Ketika kita memberikan input pada user interface OpenERP, pesan kesalahan akan ditampilkan apabila
input tidak sesuai kriteria.

62/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.6 Model, tabel database dan field


Sebagaimana dibahas sebelumnya, nama tabel database secara default adalah nama model (_name)
dengan titik diganti dengan underscore. Dengan demikian, untuk model res.partner sebagai contoh,
tabel pada database adalah res_partner. Atau, untuk model res.partner.category, tabel pada database
adalah res_partner_category.
Ketika kita menambahkan suatu field dengan cara menurunkan dari suatu model (_name sama dengan
_inherit), maka field tersebut akan ditambahkan pada tabel (untuk tipe field/pengaturan tipe field yang
mendukung).
Dari user interface OpenERP, kita bisa mengamati ini dengan:
Aktifkanlah terlebih dahulu developer mode
Buka salah satu model, misal res.partner, dengan mengakses Sales Customers. Pilihlah salah
satu partner (buka form).
Pada pilihan DebugView, pilihlah View Fields.
Sebuah dialog akan ditampilkan, berisikan field-field apa saja yang telah didefinisikan.

Apa yang kita lakukan dengan _name sama dengan _inherit adalah class inheritance, yang kita gunakan
dalam bab ini. Alternatif adalah:
63/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

_name tidak sama dengan _inherit (inheritance by prototype) dimana data disimpan pada tabel lain.
Menggunakan _inherits (inheritance by delegation).

64/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.7 Method
Class BaseModel memiliki sejumlah method yang dapat kita gunakan (langsung atau tidak) ataupun
override.
Override umumnya kita perlukan ketika fungsi yang ditawarkan perlu disesuaikan lebih lanjut. Sebagai
contoh, kita menurunkan dari res.partner dan ketika suatu partner dibuat atau diedit, kita ingin
melakukan fungsi tambahan, selain fungsi default yang telah disediakan.
Method-method yang ada dapat pula diakses lewat web service. Bacalah juga bab 9 apabila diperlukan.
Berikut adalah sejumlah method yang disediakan oleh Model. Dokumentasi yang disediakan secara
umum cukup lengkap. Kita akan membahas beberapa diantaranya setelah ini, dalam bagian-bagian
tersendiri.
Method
Argumen
__init__

self, pool, cr

browse

self, cr, uid, select, context=None, list_class=None,


fields_process=None

check_access_rights

self, cr, uid, operation, raise_exception=True

check_access_rule

self, cr, uid, ids, operation, context=None

check_field_access_rights

self, cr, user, operation, fields, context=None

check_recursion

self, cr, uid, ids, context=None, parent=None

clear_caches

self

copy

self, cr, uid, id, default=None, context=None

copy_data

self, cr, uid, id, default=None, context=None

copy_translations

self, cr, uid, old_id, new_id, context=None

create

self, cr, user, vals, context=None

default_get

self, cr, uid, fields_list, context=None

distinct_field_get

self, cr, uid, field, value, args=None, offset=0, limit=None

exists

self, cr, uid, ids, context=None

export_data

self, cr, uid, ids, fields_to_export, context=None

fields_get

self, cr, user, allfields=None, context=None, write_access=True

fields_get_keys

self, cr, user, context=None

fields_view_get

self, cr, user, view_id=None, view_type='form', context=None,


toolbar=False, submenu=False

get_external_id

self, cr, uid, ids, *args, **kwargs


65/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Method

Argumen

get_invalid_fields

self, cr, uid

get_xml_id, get_external_id

self, cr, uid, ids, *args, **kwargs

import_data

self, cr, uid, fields, datas, mode='init', current_module='',


noupdate=False, context=None, filename=None

is_transient

self

load

self, cr, uid, fields, data, context=None

log

self, cr, uid, id, message, secondary=False, context=None

name_create

self, cr, uid, name, context=None

name_get

self, cr, user, ids, context=None

name_search

self, cr, user, name='', args=None, operator='ilike', context=None,


limit=100

perm_read

self, cr, user, ids, context=None, details=True

perm_write

self, cr, user, ids, fields, context=None

read

self, cr, user, ids, fields=None, context=None, load='_classic_read'

read_group

self, cr, uid, domain, fields, groupby, offset=0, limit=None,


context=None, orderby=False

read_string

self, cr, uid, id, langs, fields=None, context=None

resolve_2many_commands

self, cr, uid, field_name, commands, fields=None, context=None

resolve_o2m_commands_to_ self, cr, uid, field_name, commands, fields=None, context=None


record_dicts,
resolve_2many_commands
search

self, cr, user, args, offset=0, limit=None, order=None, context=None,


count=False

search_count

self, cr, user, args, context=None

unlink

self, cr, uid, ids, context=None

user_has_groups

self, cr, uid, groups, context=None

view_header_get

self, cr, user, view_id=None, view_type='form', context=None

view_init

self, cr, uid, fields_list, context=None

write

self, cr, user, ids, vals, context=None

write_string

self, cr, uid, id, langs, vals, context=None

Kalau kita cermati argumen fungsi, kita akan menemukan beberapa yang umum seperti berikut.
66/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Argumen

Catatan

cr

Cursor koneksi database (SQL Query dapat dilakukan)

user, uid

Merupakan user id yang melakukan. Dalam hal ini merupakan nilai


numerik, bukan nama user (string).

ids

Id yang akan diproses. Umumnya berupa list dari id. Sebagai contoh, ketika
memanggil unlink, yang akan menghapus record, ids dapat berisikan id-id
record yang akan dihapus.

vals

Merupakan nilai penting yang berhubungan langsung dengan apa yang akan
dilakukan method. Umumnya berupa dictionary. Sebagai contoh, pada
fungsi create yang akan membuat record baru, vals dalam hal ini adalah
dictionary berisi nama field (key) dan nilainya (value).

fields

Umumnya berisi list dari nama field.

context

Informasi kontekstual, berupa dictionary. Sebagai contoh adalah language.


Lewatkanlah ke dalam pemanggilan method (apabila ada dan diharapkan).
Ketika menulis method baru, kita juga disarankan mengharapkan informasi
ini.

Bekerja dengan model lain


Untuk bekerja dengan model lain, kita bisa menggunakan self.pool.get(nama_model).

67/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.8 Mengakses OpenERP tanpa server dijalankan


Sebelum membahas beberapa contoh method, kita akan membahas terlebih dahulu bagaimana kita
dapat mengakses OpenERP dari prompt Python, bahkan tanpa server OpenERP dijalankan. Kita tidak
lakukan lewat modul ataupun web service.
Pastikanlah bahwa server database telah dijalankan/authentikasi telah dikonfigur. Kemudian,
PYTHONPATH telah diset dengan baik agar kita bisa melakukan import package/modul OpenERP.
Ada baiknya pula untuk bekerja dengan database yang bersih, tanpa modul pihak ketiga terinstall. Kita
bisa melakukan ini juga ketika server sedang berjalan.
Catatan penting: apa yang kita lakukan di sini hanyalah untuk keperluan mempelajari OpenERP
saja dan sangat tidak disarankan untuk diterapkan pada server di lingkungan produksi.
Pertama-tama, kita harus dapat mengimport modul openerp:
>>> import openerp
>>> openerp
<module 'openerp' from 'openerp/__init__.pyc'>
>>>

Langkah kedua, kita mengakses koneksi database dan pool model:


>>> db, pool = openerp.pooler.get_db_and_pool('test_buku')
No handlers could be found for logger "openerp.modules.module"
>>> db
<openerp.sql_db.Connection object at 0xb5732aac>
>>> pool
<openerp.modules.registry.Registry object at 0xb5732a2c>
>>>

Setelah itu, untuk langkah ketiga, kita melakukan inisialisasi kursor database:
>>> cr = db.cursor()
>>> cr
<openerp.sql_db.Cursor object at 0xb479a40c>
>>>

Pada langkah keempat berikut, kita akan mengakses salah satu model. Sebagai contoh, kita akan
bekerja dengan model sale_order.
>>> from openerp.addons.sale import sale

Dari manakah kita mendapatkan struktur package seperti itu? Perhatikanlah bahwa modul sale terletak
pada:
$ file openerp/addons/sale/sale.py
openerp/addons/sale/sale.py: Python script, ASCII text executable, with very long

68/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


lines

Apabila langkah keempat sukses dilakukan, kita akan melanjutkan dengan membuat instance dari
model sale.order:
>>> so = sale.sale_order.create_instance(pool, cr)
>>> so
<openerp.osv.orm.sale.order object at 0xb5407bec>
>>>

Perhatikanlah bahwa di dalam modul sale, kita memiliki class sale_order. Sementara, class sale_order
merupakan turunan dari osv.osv (orm.Model), dan kita memiliki class method create_instance.
Selanjutnya, kita tinggal menggunakan method dari Model. Kita akan membahasnya di beberapa
bagian berikut.

69/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.9 Method: search


Method search digunakan untuk melakukan pencarian dan akan mengembalikan nilai berupa list id
record yang memenuhi kriteria.
Melanjutkan dari pembahasan mengakses OpenERP tanpa server dijalankan, kita akan menggunakan
method search.
Kita akan mencari dari daftar partner yang merupakan customer. Kriteria pencarian adalah
customer=True.
Catatan: dalam OpenERP, kriteria pencarian umumnya juga dikenal dengan istilah domain.
>>> from openerp.addons.base.res import res_partner
>>> uid = 1
>>> search_data = [('customer', '=', True)]
>>> partner = res_partner.res_partner.create_instance(pool, cr)
>>> search_result = partner.search(cr, uid, search_data)
>>> search_result
[98, 69, 6, 50, 53, 17, 43, 70, 11, 55, 13, 36, 71, 16, 18, 32, 40, 7, 75, 91, 44,
37, 67, 92, 58, 56, 25, 52, 39, 41, 38, 29, 54, 61, 49, 47, 57, 48, 15, 64, 12, 31,
19, 60, 21, 63, 35, 62, 42, 34, 51, 59, 65, 46, 28, 95, 96, 97, 14, 22, 30, 27, 45,
93, 94, 33]
>>> search_result.sort()
>>> search_result
[6, 7, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 25, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 69, 70, 71, 75, 91, 92, 93, 94, 95,
96, 97, 98]
>>>

Perhatikanlah bahwa kriteria pencarian dituliskan dalam Polish Notation atau prefix notation (notasi
prefix). Sebagai contoh lain, kita akan mencari dari res.partner, untuk:
nama yang mengandung 'tes' (tidak case-sensitive) atau untuk id < 3
dan
website = ''
Karena menggunakan Polish Notation, maka operator or '|' dan and '&' ditempatkan di depan.
Pertama-tama, kita menyusun untuk kriteria pertama (or):
'|', ('name', 'ilike', 'tes'), ('id', '<', 3)

Setelah itu, kita gabungkan dengan kriteria kedua (and):


'&', '|', ('name', 'ilike', 'tes'), ('id', '<', 3), ('website', '=', '')

70/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Dan, kita tempatkan pada sebuah list:


['&', '|', ('name', 'ilike', 'tes'), ('id', '<', 3), ('website', '=', '')]

71/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.10 Method: read


Method read digunakan untuk membaca isi record dan akan mengembalikan (list dari) dictionary
dengan informasi sesuai field-field yang diminta.
Melanjutkan dari pembahasan mengakses OpenERP tanpa server dijalankan dan Method: search
sebelumnya, kita akan menggunakan method read.
Kita akan membaca dari hasil pencarian yang dilakukan sebelumnya, namun untuk partner dengan id
yang tertinggi (yang dibuat terakhir), untuk field name dan website.
>>> from openerp.addons.base.res import res_partner
>>> uid = 1
>>> partner = res_partner.res_partner.create_instance(pool, cr)
>>> search_result
[6, 7, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 25, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 69, 70, 71, 75, 91, 92, 93, 94, 95,
96, 97, 98]
>>> read_result = partner.read(cr, uid, search_result[-1], ['name', 'website'])
>>> read_result
{'website': False, 'name': u'A', 'id': 98}
>>>

72/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.11 Method: write


Method write digunakan untuk mengupdate record berdasarkan ids dan vals yang dilewatkan.
Melanjutkan dari pembahasan mengakses OpenERP tanpa server dijalankan dan Method: search
sebelumnya, kita akan menggunakan method write.
Kita akan mengupdate data dari hasil pencarian yang dilakukan sebelumnya, namun untuk partner
dengan id yang tertinggi (yang dibuat terakhir), dimana website akan kita update dengan nilai:
http://domain.tld.
>>> from openerp.addons.base.res import res_partner
>>> uid = 1
>>> partner = res_partner.res_partner.create_instance(pool, cr)
>>> search_result
[6, 7, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 25, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 69, 70, 71, 75, 91, 92, 93, 94, 95,
96, 97, 98]
>>> partner.write(cr, uid, search_result[-1], {'website': 'http://domain.tld'})
True
>>> read_result = partner.read(cr, uid, search_result[-1], ['name', 'website'])
>>> read_result
{'website': u'http://domain.tld', 'name': u'A', 'id': 98}
>>>

73/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.12 Method: create


Method create digunakan untuk membuat record baru, dan akan mengembalikan id dari record yang
dibuat.
Melanjutkan dari pembahasan mengakses OpenERP tanpa server dijalankan dan Method: search
sebelumnya, kita akan menggunakan method create untuk membuat sebuah sale_order baru.
Kita akan membuat sale_order dengan customer berupa partner dengan id yang tertinggi (yang dibuat
terakhir) dari hasil pencarian.
>>> so
<openerp.osv.orm.sale.order object at 0xb5407bec>
>>> search_result[-1]
98
>>> uid
1
>>> create_data = {
...
'partner_id': search_result[-1],
...
'partner_invoice_id': 1,
...
'partner_shipping_id': 1,
...
'pricelist_id': 1,
...
}
>>> so_id = so.create(cr, uid, create_data)
>>> so_id
17L
>>> cr.commit()
>>>

Perhatikanlah bahwa kita memanggil fungsi commit dari kursor koneksi database.

74/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.13 Method: unlink


Method unlink digunakan untuk menghapus record sesuai ids yang dilewatkan.
Melanjutkan dari pembahasan mengakses OpenERP tanpa server dijalankan dan Method: create, kita
akan menggunakan method unlink untuk menghapus sale_order yang dibuat sebelumnya.
>>> so
<openerp.osv.orm.sale.order object at 0xb5407bec>
>>> uid
1
>>> so_id
17L
>>> so.unlink(cr, uid, [so_id])
True
>>> cr.commit()
>>>

75/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.14 Program 5-1: menambah field


Pada contoh program 5-1, kita akan menambah beberapa field pada model res.partner. Pembahasan
tentang view akan dilakukan pada bab tersendiri.
Program akan didistribusikan sebagai modul OpenERP buku_partner_nop_1. Pastikanlah modul
ditempatkan pada direktori addons yang terdaftar, dan telah dilakukan update pada daftar modul.

__init__.py
from . import buku_partner_nop_1

__openerp__.py
{
'name': 'Partner 1',
'version': '1.0',
'author': 'noprianto',
'description': 'Contoh sederhana tambah field pada partner',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_1_view.xml'],

76/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


}

buku_partner_nop_1.py
from openerp.osv import orm, fields
SELECTION_1 = [
('pilihan1', 'Pilihan 1'),
('pilihan2', 'Pilihan 2'),
('pilihan3', 'Pilihan 3'),
]
SELECTION_2 = [
('pilihan4', 'Pilihan 4'),
('pilihan5', 'Pilihan 5'),
('pilihan6', 'Pilihan 6'),
('pilihan7', 'Pilihan 7'),
('pilihan8', 'Pilihan 8'),
('pilihan9', 'Pilihan 9'),
('pilihan10', 'Pilihan 10'),
]
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
def _get_selection_2(self, cr, uid, context=None):
return SELECTION_2
_columns = {
'buku_field_1': fields.char('Buku Field 1', size=20,
required=True,
help='Contoh help'),
'buku_field_2': fields.float('Buku Field 2', digits=(4, 2)),
'buku_field_3': fields.integer('Buku Field 3', size=10),
'buku_field_4': fields.boolean('Buku Field 4'),
'buku_field_5': fields.date('Buku Field 5'),
'buku_field_6': fields.datetime('Buku Field 6'),
'buku_field_7': fields.selection(SELECTION_1, 'Buku Field 7'),
'buku_field_8': fields.selection(_get_selection_2, 'Buku Field
8'),
}

buku_partner_nop_1_view.xml
<?xml version="1.0"?>
<openerp>
<data>

77/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Buku (4-1)">
<group>
<field name="buku_field_1"/>
<field name="buku_field_2"/>
<field name="buku_field_3"/>
<field name="buku_field_4"/>
<field name="buku_field_5"/>
<field name="buku_field_6"/>
<field name="buku_field_7"/>
<field name="buku_field_8"/>
</group>
</page>
</notebook>
</field>
</record>
</data>
</openerp>

78/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.15 Program 5-2: readonly dan nilai default


Pada contoh program 5-2, kita akan bekerja dengan readonly dan nilai default pada field yang
ditambahkan pada model res.partner. Pembahasan tentang view akan dilakukan pada bab tersendiri.
Program akan didistribusikan sebagai modul OpenERP buku_partner_nop_2. Pastikanlah modul
ditempatkan pada direktori addons yang terdaftar, dan telah dilakukan update pada daftar modul.

__init__.py
from . import buku_partner_nop_2

__openerp__.py
{
'name': 'Partner 2',
'version': '1.0',
'author': 'noprianto',
'description': 'Contoh sederhana readonly dan default pada field',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_2_view.xml'],
}

79/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

buku_partner_nop_2.py
from openerp.osv import orm, fields
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
_columns = {
'buku_field_9': fields.char('Buku Field 9', size=20,
readonly=True),
'buku_field_10': fields.char('Buku Field 10'),
}
_defaults = {
'buku_field_9': 'Contoh default',
'buku_field_10': lambda self, cr, uid, context: '
'.join(context.keys()),
}

buku_partner_nop_2_view.xml
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Buku (4-2)">
<group>
<field name="buku_field_9"/>
<field name="buku_field_10"/>
</group>
</page>
</notebook>
</field>
</record>
</data>
</openerp>

80/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.16 Program 5-3: constraint


Pada contoh program 5-3, kita akan bekerja dengan constraint pada field yang ditambahkan pada model
res.partner. Pembahasan tentang view akan dilakukan pada bab tersendiri.
Program akan didistribusikan sebagai modul OpenERP buku_partner_nop_3. Pastikanlah modul
ditempatkan pada direktori addons yang terdaftar, dan telah dilakukan update pada daftar modul.

__init__.py
from . import buku_partner_nop_3

__openerp__.py
{
'name': 'Partner 3',
'version': '1.0',
'author': 'noprianto',
'description': 'Contoh sederhana constraint pada field',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_3_view.xml'],
}

81/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

buku_partner_nop_3.py
from openerp.osv import orm, fields
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
_columns = {
'buku_field_11': fields.char('Buku Field 11', size=20,
required=True),
}
_defaults = {
'buku_field_11': 'hello',
}
def _check_field_11(self, cr, uid, ids, context=None):
for i in self.browse(cr, uid, ids, context=context):
if len(i.buku_field_11) >= 3:
return True
return False
_constraints = (
[_check_field_11, 'Panjang harus minimal 3 karakter',
['buku_field_11']],
)

buku_partner_nop_3_view.xml
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Buku (4-3)">
<group>
<field name="buku_field_11"/>
</group>
</page>
</notebook>
</field>

82/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


</record>
</data>
</openerp>

83/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.17 Program 5-4: field functional


Pada contoh program 5-4, kita akan menambahkan field functional pada model res.partner.
Pembahasan tentang view akan dilakukan pada bab tersendiri.
Program akan didistribusikan sebagai modul OpenERP buku_partner_nop_4. Pastikanlah modul
ditempatkan pada direktori addons yang terdaftar, dan telah dilakukan update pada daftar modul.
__init__.py
from . import buku_partner_nop_4

__openerp__.py
{
'name': 'Partner 4',
'version': '1.0',
'author': 'noprianto',
'description': 'Contoh sederhana field functional',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_4_view.xml'],
}

buku_partner_nop_4.py
import random
from openerp.osv import orm, fields
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
def _function_test(self, cr, uid, ids, field, arg, context=None):
res = {}
for i in ids:
res[i] = random.random()
return res
_columns = {
'buku_field_12': fields.function(_function_test, type='float')
}

buku_partner_nop_4_view.xml
84/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Buku (4-4)">
<group>
<field name="buku_field_12" string="Buku Field 12
(function)"/>
</group>
</page>
</notebook>
</field>
</record>
</data>
</openerp>

85/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

5.18 Program 5-5: method create/write


Pada contoh program 5-5, kita akan melakukan override method create dan write milik model
res.partner.
Program akan didistribusikan sebagai modul OpenERP buku_partner_nop_5. Pastikanlah modul
ditempatkan pada direktori addons yang terdaftar, dan telah dilakukan update pada daftar modul.
__init__.py
from . import buku_partner_nop_5

__openerp__.py
{
'name': 'Partner 5',
'version': '1.0',
'author': 'noprianto',
'description': 'Contoh sederhana override method create/write',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
}

buku_partner_nop_5.py
from openerp.osv import orm, fields
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
def write(self, cr, user, ids, vals, context=None):
comment = vals.get('comment', '')
try:
comment = comment.strip()
vals['comment'] = comment
except AttributeError:
pass
return super(res_partner, self).write(cr, user, ids, vals, context)
def create(self, cr, user, vals, context=None):
comment = vals.get('comment', '')
try:
comment = comment.strip()
vals['comment'] = comment
except AttributeError:
pass
return super(res_partner, self).create(cr, user, vals, context)

86/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6. Dasar-dasar View
Penulis: Noprianto
Pada bab-bab sebelumnya, kita telah melihat view yang didefinisikan dalam file-file XML. Di bab ini,
kita akan membahas lebih lanjut tentang dasar-dasar view pada OpenERP. Termasuk bagaimana
menambahkan menu/menu item.
OpenERP mendukung beberapa macam tipe view. Namun, kita hanya akan membahas tentang form
dan tree. Form digunakan untuk menampilkan suatu record secara detil. Sementara, tree digunakan
untuk menampilkan beberapa record sekaligus (list). Keduanya dapat pula digunakan untuk
menambahkan/mengedit data, walau pada tree, ini akan lebih terbatas.
Pembahasan akan dilakukan langsung pada contoh modul.
Catatan: definisi view umumnya ditempatkan dalam sub direktori view dalam modul.

6.1 Kerangka
Berikut ini adalah kerangka definisi view dalam sebuah file XML:
<?xml version="1.0"?>
<openerp>
<data>
<definisi view>
.
.
.
<definisi view>
</data>
</openerp>

Di dalam bab ini, kita akan menggunakan tag-tag berikut:


<record> dengan atribut model=ir.ui.view, untuk mendefinisikan view itu sendiri.
<record> dengan atribut model=ir.actions.act_window, untuk link action ke view.
<menuitem>, untuk membuat entri pada menu dan link ke action.
Contoh 1:
<record model="ir.ui.view" id="view_partner_form">

</record>

87/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Contoh 2:
<record model="ir.ui.view" id="view_catatan_tree">

</record>

Contoh 3:
<record model="ir.actions.act_window" id="action_buku_catatan_tree">

</record>

Contoh 4:
<menuitem name="Buku" id="menu_buku"/>

Di dalam setiap <record>, kita umumnya bekerja dengan tag <field> dengan berbagai atribut, <form>
dengan berbagai elemen di dalamnya, <tree> ataupun lainnya.
Berikut adalah contoh tag <field>:
<field
<field
<field
<field

name="name">res.partner.form</field>
name="model">res.partner</field>
name="inherit_id" ref="base.view_partner_form"/>
name="arch" type="xml">

</field>

Mari kita lihat lebih lanjut dalam contoh pembahasan modul.

88/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.2 Field pada model


Untuk merujuk pada suatu field pada model, kita menggunakan tag <field> dengan atribut
name=nama_field, sebagai contoh:
<field name="fax"/>

Lebih lanjut, terdapat sejumlah atribut tambahan yang bisa diberikan pada tag ini, yang mana akan
memiliki arti/efek.
Contoh 1:
<field name="fax" position="replace"/>

Contoh 2:
<field name="mobile" position="before">
<field name="fax"/>
</field>

Contoh 3:
<field name="buku_field_17" password="True" nolabel="1" colspan="2"/>

Contoh 4:
<field name="buku_field_18" attrs="{'required': ['&amp;', ('is_company', '=',
False), ('street', '=', False)]}"/>

89/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.3 Inheritance pada view


Ketika kita menurunkan dari suatu model, misal untuk menambah field, kita umumnya fokus pada apa
yang kita tambahkan tersebut. Walau, tentu saja, kita selalu bisa merujuk pada field-field yang ada
sebelumnya.
Begitupun juga dengan view. View dapat diturunkan, dan kita bisa fokus pada perubahan spesifik yang
ingin kita lakukan.
Perubahan spesifik yang dimaksud tidak harus selalu mendefinisikan bagaimana field yang kita
tambahkan, dapat ditampilkan. Kita tidak harus selalu menambahkan field dan mendefinisikan pada
view. Ketika menurunkan dari suatu view, kita bisa mengubah apa yang telah didefinisikan
sebelumnya.
Dengan demikian, sama seperti pada model, ketika kita ingin mengubah suatu view yang ada, kita tidak
edit langsung. Tapi, kita turunkan dan lakukan perubahan pada apa yang kita kerjakan.
Untuk menurunkan, kita perlu mengetahui id sebuah view. Salah satu cara nyaman untuk mengetahui id
suatu view aktif adalah dengan mengaktifkan developer mode dan memilih Manage Views pada pilihan
yang ada.
Untuk mencoba, bukalah informasi detil untuk partner tertentu (form). Kemudian, pilihlah Manage
Views. Dari popup yang tampil, kita bisa melihat berbagai informasi yang ada, termasuk External ID.
Id tersebut dapat kita gunakan pada tag <field> dengan atribut name=inherit_id, seperti pada contoh
berikut:
<field name="inherit_id" ref="base.view_partner_form"/>

90/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Catatan: pada saat kita mendefinisikan view, kita juga memberikan nilai id unik per modul.

91/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.4 Form: mengatur ulang posisi field


Dalam contoh modul buku_partner_nop_6, kita bekerja pada model res.partner dan akan mengatur
ulang posisi field, dimana posisi fax dan mobile akan kita tukar. Pada modul ini, kita tidak menambah
field apapun pada model res.partner.

Berikut adalah definisi view selengkapnya (buku_partner_nop_6_view.xml):


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<data>
<field name="fax" position="replace"/>
<field name="mobile" position="before">
<field name="fax"/>
</field>
</data>
</field>
</record>

92/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


</data>
</openerp>

Mari kita fokus pada blok:


<data>
<field name="fax" position="replace"/>
<field name="mobile" position="before">
<field name="fax"/>
</field>
</data>

Tag <data> dapat digunakan untuk perubahan pada beberapa lokasi sekaligus.

Apa yang kita lakukan adalah:


Menghapus field fax. Menghapus dapat dilakukan dengan memberikan atribut position=replace
(mengganti dengan sebuah elemen kosong).
<field name="fax" position="replace"/>

Menambah field fax sebelum field mobile. Kita akan mulai dari field mobile dengan
position=before, barulah mendefinisikan field fax di dalamnya.
<field name="mobile" position="before">
<field name="fax"/>
</field>

File __openerp__.py dalam modul:


{
'name': 'Partner 6',
'version': '1.0',
'author': 'noprianto',
'description': 'form view (partner), atur posisi field',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_6_view.xml'],
}

Sementara __init__.py merupakan file kosong.

93/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.5 Form: menambah field


Dalam contoh modul buku_partner_nop_7, kita bekerja pada model res.partner dan menambahkan
beberapa field. Sebagian dari field yang ditambahkan pada model, akan didefinisikan pada view,
dengan pengaturan posisi tertentu.

Field yang ditambahkan (file buku_partner_nop_7.py):


from openerp.osv import orm, fields
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
_columns = {
'buku_field_13':
'buku_field_14':
'buku_field_15':
'buku_field_16':
'buku_field_17':
'buku_field_18':
'buku_field_19':
'buku_field_20':

fields.char('Buku
fields.char('Buku
fields.char('Buku
fields.char('Buku
fields.char('Buku
fields.char('Buku
fields.char('Buku
fields.char('Buku

94/232

Field
Field
Field
Field
Field
Field
Field
Field

13',
14',
15',
16',
17',
18',
19',
20',

size=10),
size=10),
size=10),
size=10),
size=10),
size=10),
size=10),
size=10),

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


}

Berikut adalah definisi view selengkapnya (buku_partner_nop_7_view.xml):


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<data>
<field name="website" position="before">
<field name="buku_field_13"/>
</field>
<field name="website" position="after">
<field name="buku_field_14"/>
</field>
<field name="website" position="replace"/>
</data>
</field>
</record>
</data>
</openerp>

Apa yang kita lakukan adalah:


Menambahkan field buku_field_13 sebelum website.
<field name="website" position="before">
<field name="buku_field_13"/>
</field>

Menambahkan field buku_field_14 setelah website.

<field name="website" position="after">


<field name="buku_field_14"/>
</field>

Menghapus field website (menggantikan dengan elemen kosong).


<field name="website" position="replace"/>

95/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

File __openerp__.py dalam modul:


{
'name': 'Partner 7',
'version': '1.0',
'author': 'noprianto',
'description': 'form view (partner), tambah/hapus field',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_7_view.xml'],
}

File __init__.py dalam module:


from . import buku_partner_nop_7

96/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.6 Form: notebook dan group


Dalam contoh modul buku_partner_nop_8, kita bekerja pada model res.partner dan akan
mengelompokkan beberapa field yang ditambahkan pada buku_partner_nop_7, dalam notebook dan
group tersendiri.

Berikut adalah definisi view selengkapnya (buku_partner_nop_8_view.xml):


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="buku_partner_nop_7.view_partner_form"/>
<field name="arch" type="xml">
<field name="buku_field_13" position="replace"/>
<field name="buku_field_14" position="replace"/>
<notebook>
<page string="contoh notebook/page">
<label for="buku_field_13"/>
<field name="buku_field_13"/>
<group string="contoh group">

97/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<field name="buku_field_14"/>
</group>
<group string="contoh group 2 (6 kolom)" col="6">
<field name="buku_field_15" colspan="4"/>
<field name="buku_field_16"/>
</group>
</page>
</notebook>
</field>
</record>
</data>
</openerp>

Apa yang kita lakukan adalah:


Membuat sebuah notebook/tab terpisah, didefinisikan dengan <notebook> dan <page>.
<notebook>
<page string="contoh notebook/page">

</page>
</notebook>

Menambahkan sebuah field di dalam page tersebut. Per OpenERP versi 7.0, <field
name=nama_field/> tidak menampilkan label, kecuali ditempatkan di dalam <group>. Oleh
karena itu, kita menggunakan <label for=nama_field/> seperti pada contoh.
<label for="buku_field_13"/>
<field name="buku_field_13"/>

Kita membuat sebuah group baru, yang bisa digunakan untuk mengelompokkan sejumlah kolom
dan kemudian membaginya kembali menjadi kolom-kolom. Per OpenERP versi 7.0, jumlah kolom
default dalam group adalah 2, kecuali kita menentukan secara eksplisit dengan atribut col=n.
Group bisa diberikan label/title seperti pada contoh. Kita tambahkan sebuah field ke dalam group
tersebut.
<group string="contoh group">
<field name="buku_field_14"/>
</group>

Kemudian, kita buat satu group lagi dengan jumlah kolom adalah 6. Lalu kita tambahkan dua field,
yang pertama menempati 4 kolom (dengan atribut colspan=n) dan yang kedua menempati
sisanya. Perhatikanlah bahwa label secara otomatis ditambahkan karena dibawah <group>.
98/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

<group string="contoh group 2 (6 kolom)" col="6">


<field name="buku_field_15" colspan="4"/>
<field name="buku_field_16"/>
</group>

Dalam contoh ini, kita turunkan view dari:


<field name="inherit_id" ref="buku_partner_nop_7.view_partner_form"/>

Modul juga membutuhkan buku_partner_nop_7 sebagaimana didefinisikan pada __openerp__.py:


{
'name': 'Partner 8',
'version': '1.0',
'author': 'noprianto',
'description': 'form view (partner), group',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['buku_partner_nop_7'],
'data': ['buku_partner_nop_8_view.xml'],
}

Sementara __init__.py merupakan file kosong.

99/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.7 Form: attrs dan atribut lain


Dalam contoh modul buku_partner_nop_9, kita bekerja pada model res.partner dan akan bekerja
dengan beberapa field yang ditambahkan pada buku_partner_nop_7.

Kita akan membuat sebuah tab baru, namun tab tersebut hanya tampil apabila partner adalah
perorangan, bukan perusahaan. Apabila Is a Company? di centang, maka tab ini tidak ditampilkan.
Lebih lanjut lagi, di dalam tab tersebut, kita tambahkan dua field, di mana salah satunya, akan menjadi
required (harus diisi) apabila:
Partner bukanlah perusahaan, dan
Alamat (street) tidak diisikan.
Berikut adalah definisi view selengkapnya (buku_partner_nop_9_view.xml):
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="buku_partner_nop_7.view_partner_form"/>

100/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<field name="priority" eval="100"/>
<field name="arch" type="xml">
<notebook>
<page string="Bukan perusahaan" attrs="{'invisible':
[('is_company', '=', True)]}">
<group>
<field name="buku_field_17" password="True"
nolabel="1" colspan="2"/>
<field name="buku_field_18" attrs="{'required':
['&amp;', ('is_company', '=', False), ('street', '=', False)]}"/>
</group>
</page>
</notebook>
</field>
</record>
</data>
</openerp>

Apa yang kita lakukan adalah:


Menambahkan satu page dengan atribut attrs. Format atribut ini adalah:
{'atribut 1': [('nama_field 1', 'operator', nilai),...], }
dimana atribut adalah: readonly (tidak dapat diubah), invisible (tidak ditampilkan), required
(harus diisi).
Nilai default adalah {}
Atribut yang kita tambahkan pada page tersebut menentukan page tersebut akan invisible (tidak
ditampilkan) apabila kondisi berikut terpenuhi: [('is_company', '=', True)]

<page
[('is_company', '=', True)]}">

string="Bukan

perusahaan"

attrs="{'invisible':

</page>

Menambahkan satu field dengan atribut password=True (input password/masked), nolabel=1


(tidak menampilkan label) dan colspan=2 (menempati dua kolom).
<field name="buku_field_17" password="True" nolabel="1" colspan="2"/>

Menambahkan satu field lagi, dengan atribut attrs, di mana field akan required apabila kondisi
berikut terpenuhi (&amp; untuk operator &) : ['&amp;', ('is_company', '=', False),
('street', '=', False)]
<field name="buku_field_18" attrs="{'required': ['&amp;', ('is_company', '=',

101/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


False), ('street', '=', False)]}"/>

Catatan: eval digunakan untuk evaluasi ekspresi Python, digunakan untuk nilai non string.
Sama

seperti

sebelumnya,

dalam

buku_partner_nop_7.view_partner_form

contoh
ini,
kita
turunkan
view
dari
dan modul juga membutuhkan buku_partner_nop_7.

File __openerp__.py dalam modul:


{
'name': 'Partner 9',
'version': '1.0',
'author': 'noprianto',
'description': 'form view (partner), atribut field',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['buku_partner_nop_7'],
'data': ['buku_partner_nop_9_view.xml'],
}

Sementara __init__.py merupakan file kosong.

102/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.8 Form: on change


Dalam contoh modul buku_partner_nop_10, kita bekerja pada model res.partner, dan ketika isi suatu
field berubah, fungsi tertentu akan dipanggil. Dalam contoh ini, apa yang dilakukan oleh fungsi akan
mengembalikan nilai dengan aturan tertentu, yang diartikan sebagai menampilkan pesan.

Berikut adalah definisi view selengkapnya (buku_partner_nop_10_view.xml):


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="buku_partner_nop_7.view_partner_form"/>
<field name="arch" type="xml">
<field name="title" position="after">
<field name="buku_field_19"
on_change="onchange_buku_field_19(buku_field_19)"/>
</field>
</field>
</record>
</data>
</openerp>

103/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Dan, berikut adalah definisi fungsi yang dipanggil, dalam file buku_partner_nop_10.py:
from openerp.osv import orm
class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
def onchange_buku_field_19(self, cr, uid, ids, buku_field_19, context=None):
ret = {}
ret['warning'] = {
'title': 'Pesan',
'message': 'Isi field buku_field_19 adalah %s' %
(buku_field_19),
}
return ret

Apa yang kita lakukan adalah menambahkan satu field, dengan atribut on_change, dengan nilai
statement pemanggilan fungsi on change, lengkap dengan argumen berupa nama field. Nama field
harus didefinisikan dalam view.
<field name="buku_field_19" on_change="onchange_buku_field_19(buku_field_19)"/>

Fungsi yang dipanggil setidaknya harus menerima argumen cr, uid, ids sebagaimana method lain
(seperti dibahas pada Bab 4), apa yang ingin kita lewatkan, dan sebuah context (sebagaimana
disarankan, disinggung pada Bab 4). Fungsi tersebut dapat merujuk ke record lain yang telah tersimpan
dalam database.
def onchange_buku_field_19(self, cr, uid, ids, buku_field_19, context=None):

Nilai kembalian fungsi, sebuah dictionary, akan menentukan apa yang akan dilakukan sesuai key:
domain: dictionary berupa domain {field: domain}.
value: dictionary berupa nilai field baru: {field: value}. Ini bisa lebih dari satu field, sebagaimana
dibahas pada contoh berikutnya. Dapat memicu pemanggilan fungsi on change pada field lain,
apabila didefinisikan.
warning: dictionary dengan key title (judul) dan message (pesan), yang digunakan untuk
menampilkan pesan. Ini adalah yang kita lakukan dalam contoh ini.
ret = {}
ret['warning'] = {
'title': 'Pesan',

104/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


'message': 'Isi field buku_field_19 adalah %s' %
(buku_field_19),
}
return ret

Catatan: fungsi on change dapat digunakan pada saat record sedang dibuat dan belum disimpan pada
database. Fungsi ini dapat membaca dari database, namun tidak seharusnya menulis ke database.
Sama

seperti

sebelumnya,

dalam

buku_partner_nop_7.view_partner_form

contoh
ini,
kita
turunkan
view
dari
dan modul juga membutuhkan buku_partner_nop_7.

File __openerp__.py dalam modul:


{
'name': 'Partner 10',
'version': '1.0',
'author': 'noprianto',
'description': 'form view (partner), on change 1',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['buku_partner_nop_7'],
'data': ['buku_partner_nop_10_view.xml'],
}

File __init__.py dalam modul:


from . import buku_partner_nop_10

105/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.9 Form: on change (2)


Dalam contoh modul buku_partner_nop_11, kita bekerja pada model res.partner, dan akan menukar
nilai field satu dengan field lainnya, apabila isi dari suatu field berubah.

Berikut adalah definisi view selengkapnya (buku_partner_nop_11_view.xml):


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="buku_partner_nop_7.view_partner_form"/>
<field name="arch" type="xml">
<field name="title" position="after">
<field name="buku_field_20"
on_change="onchange_buku_field_20(buku_field_20, buku_field_19)"/>
</field>
</field>
</record>
</data>
</openerp>

Dan, berikut adalah definisi fungsi on change yang dipanggil, dalam file buku_partner_nop_11.py:
106/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

from openerp.osv import orm


class res_partner(orm.Model):
_name = 'res.partner'
_inherit = 'res.partner'
def onchange_buku_field_20(self, cr, uid, ids, buku_field_20,
buku_field_19, context=None):
ret = {}
ret['value'] = {
'buku_field_20': buku_field_19,
'buku_field_19': buku_field_20,
}
return ret

Sebagaimana dibahas pada contoh sebelumnya, fungsi mengembalikan dictionary dengan key berupa
value, dengan nilai berupa isi field yang telah ditukar.
Kita lihat bahwa fungsi bekerja dengan isi dua field dilewatkan:
<field
name="buku_field_20"
buku_field_19)"/>

on_change="onchange_buku_field_20(buku_field_20,

Apabila modul pada contoh sebelumnya terinstall, maka ini akan memicu pemanggilan on change.
Sama

seperti

sebelumnya,

dalam

contoh
ini,
kita
turunkan
view
dari
buku_partner_nop_7.view_partner_form dan modul juga membutuhkan buku_partner_nop_7.
File __openerp__.py dalam modul:
{
'name': 'Partner 11',
'version': '1.0',
'author': 'noprianto',
'description': 'form view (partner), on change 2',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['buku_partner_nop_7'],
'data': ['buku_partner_nop_11_view.xml'],
}

File __init__.py dalam modul:


from . import buku_partner_nop_11

107/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.10 Tree: tambah/hapus field


Dalam contoh modul buku_partner_nop_12, kita bekerja pada model res.partner, pada tree view (list),
dimana:
Field email kita hapus.
Field website kita tambahkan, sebelum phone.
Pada modul ini, kita tidak menambah field apapun pada model res.partner.

Berikut adalah definisi view selengkapnya (buku_partner_nop_12_view.xml):


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_partner_tree">
<field name="name">res.partner.tree</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/>
<field name="arch" type="xml">
<data>
<field name="email" position="replace"/>
<field name="phone" position="before">
<field name="website"/>
</field>

108/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


</data>
</field>
</record>
</data>
</openerp>

Apa yang berbeda dengan contoh sebelumnya (5.4, modul buku_partner_nop_6), dari sisi inheritance,
selain field yang terlibat, adalah:
<field name="inherit_id" ref="base.view_partner_tree"/>

Di mana nilai base.view_partner_tree kita dapatkan dari popup Manage Views dengan developer mode
diaktifkan.
File __openerp__.py dalam modul:
{
'name': 'Partner 12',
'version': '1.0',
'author': 'noprianto',
'description': 'tree view (partner), tambah/sembunyikan field',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_12_view.xml'],
}

Sementara __init__.py merupakan file kosong.

109/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

6.11 Menuitem dan editable tree


Dalam contoh ini, kita membuat model buku.catatan, dalam modul buku_catatan, dimana ketika
terinstall, sebuah menu/menuitem baru akan ditambahkan. Selain itu, tree view juga kita gunakan untuk
menambahkan/mengedit.

110/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

111/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Berikut adalah model yang dibuat, dalam file buku_catatan.py:


from openerp.osv import orm, fields
class res_partner(orm.Model):
_name = 'buku.catatan'
_description = 'Catatan'
_columns = {
'title': fields.char('Title', size=32, required=True),
'content': fields.text('Content'),
}

Dan, berikut adalah definisi view selengkapnya (buku_catatan_view.xml):


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_catatan_form">
<field name="name">buku.catatan.form</field>

112/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<field name="model">buku.catatan</field>
<field name="arch" type="xml">
<form string="Catatan">
<group>
<field name="title"/>
<field name="content"/>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_catatan_tree">
<field name="name">buku.catatan.tree</field>
<field name="model">buku.catatan</field>
<field name="arch" type="xml">
<tree string="Catatan" editable="bottom">
<field name="title"/>
<field name="content"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_buku_catatan_tree">
<field name="name">Catatan</field>
<field name="res_model">buku.catatan</field>
</record>
<menuitem name="Buku" id="menu_buku"/>
<menuitem name="Catatan" id="menu_buku_catatan" parent="menu_buku"/>
<menuitem name="Catatan" id="menu_buku_catatan_tree"
parent="menu_buku_catatan" action="action_buku_catatan_tree"/>
</data>
</openerp>

Form didefinisikan dengan:


<form string="Catatan">
<group>
<field name="title"/>
<field name="content"/>
</group>
</form>

Editable tree, dalam hal ini didefinisikan dengan:


<tree string="Catatan" editable="bottom">
<field name="title"/>
<field name="content"/>

113/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


</tree>

Action didefinisikan dengan:


<record model="ir.actions.act_window" id="action_buku_catatan_tree">
<field name="name">Catatan</field>
<field name="res_model">buku.catatan</field>
</record>

Catatan: gunakan <field name="view_id" ref="id_view_yang_ingin_ditampilkan"/> untuk secara


eksplisit menentukan view yang ingin ditampilkan.
Untuk hirarki menuitem, perhatikanlah atribut parent (ke id). Perhatikanlah juga link ke action yang
kita definisikan sebelumnya (atribut action).
<menuitem name="Buku" id="menu_buku"/>
<menuitem name="Catatan" id="menu_buku_catatan" parent="menu_buku"/>
<menuitem name="Catatan" id="menu_buku_catatan_tree"
parent="menu_buku_catatan" action="action_buku_catatan_tree"/>

File __openerp__.py dalam modul:


{
'name': 'Catatan',
'version': '1.0',
'author': 'noprianto',
'description': 'catatan sederhana',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_catatan_view.xml'],
}

File __init__.py dalam modul:


from . import buku_catatan

114/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

7. Dasar-dasar Report
Penulis: Noprianto

Untuk membuat report sendiri di OpenERP, kita memiliki beberapa pilihan cara. Yang akan kita bahas
dalam bab ini adalah penggunaan RML, yang merupakan cara original dalam membuat report di
OpenERP. Cara lain juga tersedia, baik yang datang bersama OpenERP ataupun menggunakan modul
dari pihak lain.
Report dapat ikut pada model, seperti ketika kita memilih beberapa record dari res.partner, kemudian
klik pada tombol Print dan memilih report yang tersedia. Report juga dapat ditempatkan pada
menu/menuitem tersendiri. Apabila parameter dibutuhkan dalam menghasilkan report, kita bisa
menggunakan wizard.
Pembahasan akan dilakukan langsung pada contoh modul.
Catatan: definisi wizard umumnya ditempatkan dalam sub direktori wizard dan definisi report
umumnya ditempatkan dalam sub direktori report.

7.1 Definisi
Sebagaimana halnya view, report juga didefinisikan di dalam file XML.
<?xml version="1.0"?>
<openerp>
<data>
<definisi report>
.
.
.
<definisi report>
</data>
</openerp>

Untuk mendefinisikan report, kita gunakan tag <report> dengan sejumlah atribut. Di dalam bab ini, kita
akan menggunakan:
id: id report (unik).
name: nama report (dibutuhkan).
string: judul report (dibutuhkan).
model: model dimana report didefinisikan (dibutuhkan).
rml: path ke file RML, relatif terhadap addons (apabila digunakan).
auto: apabila False, custom parser digunakan.
header: apabila False, header tidak digunakan.
115/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Contoh:
<report
id="report_buku_partner_nop_13"
name="buku.partner.nop.13"
string="Report 13"
model="res.partner"
rml="buku_partner_nop_13/report.rml"
auto="True"
header="False"/>

116/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

7.2 Report dengan RML


Untuk membuat report dengan RML:
Kita perlu membuat satu file RML, yang secara sintaks, merupakan file XML.
Kita tidak membutuhkan modul tambahan pada OpenERP.
Kita juga tidak membutuhkan program/service lain yang berjalan di server, selain OpenERP.
Salah satu kekurangan bekerja dengan RML adalah harus menulis kode RML itu sendiri. Untungnya:
Dokumentasi RML sendiri cukup lengkap. Untuk informasi selengkapnya, kunjungilah
http://www.reportlab.com.
OpenERP datang bersama modul base_report_designer yang menyediakan plugin untuk
OpenOffice, dimana kita bisa mendesain report dengan OpenOffice, dan kemudian mengekspor ke
file RML. Fitur pelengkap lain juga disediakan. Pembahasan modul base_report_designer berada di
luar cakupan bab ini.
File RML akan di-parse oleh OpenERP dan report dalam format PDF akan dihasilkan. Kita dapat
menentukan ukuran kertas apabila diperlukan.

117/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

7.3 Kerangka RML


Berikut adalah kerangka isi file RML yang kita gunakan dalam bab ini:
<?xml version="1.0"?>
<document filename="report.pdf">
<template pageSize="(612, 792)" title="Report">
<pageTemplate id="page">
<frame id="page" x1="30.0" y1="30.0" width="552" height="732"/>
</pageTemplate>
</template>
<stylesheet>
<blockTableStyle id="Table">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
<lineStyle kind="GRID" colorName="#000000" start="0,0" stop="-1,-1"/>
</blockTableStyle>
<paraStyle name="Standard" fontName="Courier"/>
</stylesheet>
<story>
</story>
</document>

Di dalam kerangka tersebut, kita:


Menentukan template, termasuk ukuran kertas (contoh: pageSize="(612, 792)", dalam 1/72
inch).
Menentukan nomor halaman (dalam contoh 7.4)
Menentukan style (misal untuk tabel dan paragraf). Khusus untuk paragraf, kerangka tersebut
menggunakan font Courier.
Akan menambahkan paragraf dalam blok <story>
Akan menambahkan tabel dalam blok <story>

118/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

7.4 Report pada model


Dalam contoh modul buku_partner_nop_13, kita bekerja pada model res.partner dan akan
menambahkan satu report. Untuk menghasilkan report, satu atau lebih record harus dipilih terlebih
dahulu. Setelah itu, kita dapat klik pada tombol Print dan memilih Report 13 dari daftar.

Berikut adalah definisi report selengkapnya (buku_partner_nop_13_report.xml):


<?xml version="1.0"?>
<openerp>
<data>
<report
id="report_buku_partner_nop_13"
name="buku.partner.nop.13"
string="Report 13"
model="res.partner"
rml="buku_partner_nop_13/report.rml"
auto="True"
header="False"/>
</data>
</openerp>

119/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Dari definisi tersebut, bisa kita lihat bahwa kita akan bekerja dengan model res.partner, tanpa
penggunaan custom parser dan tidak menambahkan header pada laporan.
Laporan sendiri akan dihasilkan dari file report.rml:
<?xml version="1.0"?>
<document filename="report.pdf">
<template pageSize="(612, 792)" title="Report">
<pageTemplate id="page">
<frame id="page" x1="30.0" y1="30.0" width="552" height="732"/>
</pageTemplate>
</template>
<stylesheet>
<blockTableStyle id="Table">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
<lineStyle kind="GRID" colorName="#000000" start="0,0" stop="-1,-1"/>
</blockTableStyle>
<paraStyle name="Standard" fontName="Courier"/>
</stylesheet>
<story>
<para style="Standard">Report 13<br/><br/></para>
<blockTable colWidths="100,200,252" repeatRows="1" style="Table">
<tr>
<td>
<para style="Standard">ID</para>
</td>
<td>
<para style="Standard">Nama</para>
</td>
<td>
<para style="Standard">Website</para>
</td>
</tr>
<tr>
<td>
<para style="Standard">[[ repeatIn(objects, 'o') ]]</para>
<para style="Standard">[[ o.id ]]</para>
</td>
<td>
<para style="Standard">[[ o.name ]]</para>
</td>
<td>
<para style="Standard">[[ o.website ]]</para>
</td>
</tr>
</blockTable>
</story>

120/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


</document>

Apa yang kita buat dalam file RML tersebut adalah:


Menambahkan paragraf, menggunakan style 'Standard', termasuk dalam sel tabel.
<para style="Standard">Report 13<br/><br/></para>
<para style="Standard">[[ o.website ]]</para>

Menambahkan tabel, dengan tiga kolom sesuai ukuran lebar, menggunakan style 'Table' dan baris
pertama akan diulang. Baris dan kolom mirip dengan pada HTML.
<blockTable colWidths="100,200,252" repeatRows="1" style="Table">
</blockTable>

Yang perlu kita perhatikan sehubungan ekspresi pada OpenERP adalah:


Kode dalam [[ ]] akan dievaluasi sebagai ekspresi Python.
objects akan berisikan list dari record yang ada. Apabila kita memilih 3 record, maka objects juga
akan terdiri dari 3 record.
Dalam contoh tersebut, kita menggunakan fungsi repeatIn(list, 'var', 'tag'). Fungsi ini akan
mengulang parent elemen tag untuk setiap object dalam list. Object dapat diakses dengan variabel
var selama perulangan.
Variabel o kita gunakan untuk setiap object.
Karena kita bekerja dengan model res.partner, maka field id, name dan website tersedia.
Berikut adalah isi file __openerp__.py:
{
'name': 'Partner 13',
'version': '1.0',
'author': 'noprianto',
'description': 'partner, laporan sederhana',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_13_report.xml'],
}

Sementara __init__.py merupakan file kosong.

121/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

7.5 Custom parser


Dalam contoh modul buku_partner_nop_14, kita bekerja pada model res.partner dan akan
menambahkan satu report. Untuk menghasilkan report, satu atau lebih record harus dipilih terlebih
dahulu. Setelah itu, kita dapat klik pada tombol Print dan memilih Report 14 dari daftar.
Berbeda dengan contoh sebelumnya, kita akan menggunakan custom parser untuk report yang kita
buat.
Custom parser memungkinkan kita untuk menambahkan fungsi tertentu ke dalam report. Sebagai
contoh, dengan parser default, kita bisa mengakses diantaranya beberapa informasi berikut, dalam
report, sebagai ekspresi Python ([[ ]]):
user: object user OpenERP
repeatIn seperti dibahas sebelumnya
time: modul time
Custom parser yang kita buat diturunkan dari class rml_parse dalam modul report_sxw.py, dalam
package openerp.report.
Apa yang akan kita lakukan dalam contoh ini adalah menambah akses untuk modul random pada
localcontext, yang akan dilewatkan pada report, sehingga kita bisa menggunakannya dalam report.
Contoh lain dalam penggunaan OpenERP sehari-hari adalah penambahan fungsi terbilang.

122/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Berikut adalah definisi report selengkapnya (buku_partner_nop_14_report.xml):


<?xml version="1.0"?>
<openerp>
<data>
<report
id="report_buku_partner_nop_14"
name="buku.partner.nop.14"
string="Report 14"
model="res.partner"
rml="buku_partner_nop_14/report.rml"
auto="False"
header="False"/>
</data>
</openerp>

Karena kita menggunakan custom parser, auto kita berikan nilai False.
Laporan sendiri akan dihasilkan dari file report.rml:
<?xml version="1.0"?>
<document filename="report.pdf">
<template pageSize="(612, 792)" title="Report">
<pageTemplate id="page">
<frame id="page" x1="30.0" y1="30.0" width="552" height="732"/>
<pageGraphics>
<setFont name="Courier" size="8"/>
<drawString x="30" y="20">Halaman <pageNumber/></drawString>
</pageGraphics>
</pageTemplate>
</template>
<stylesheet>
<blockTableStyle id="Table">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
<lineStyle kind="GRID" colorName="#000000" start="0,0" stop="-1,-1"/>
</blockTableStyle>
<paraStyle name="Standard" fontName="Courier"/>
</stylesheet>
<story>
<para style="Standard">Report 14<br/><br/></para>
<para style="Standard">[[ time.asctime() ]]<br/><br/></para>
<para style="Standard">[[ user.name ]]<br/><br/></para>
<para style="Standard">[[ random.random() ]]<br/><br/></para>
<blockTable colWidths="100,200,252" repeatRows="1" style="Table">

123/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<tr>
<td>
<para style="Standard">ID</para>
</td>
<td>
<para style="Standard">Nama</para>
</td>
<td>
<para style="Standard">Website</para>
</td>
</tr>
<tr>
<td>
<para style="Standard">[[ repeatIn(objects, 'o') ]]</para>
<para style="Standard">[[ o.id ]]</para>
</td>
<td>
<para style="Standard">[[ o.name ]]</para>
</td>
<td>
<para style="Standard">[[ o.website ]]</para>
</td>
</tr>
</blockTable>
</story>
</document>

Untuk menambahkan nomor halaman, kita bisa tempatkan dalam blok <pageGraphics> di dalam
<pageTemplate>. Untuk menggambar string, kita gunakan tag <drawString> pada posisi x dan y
tertentu. Nomor halaman aktif didapatkan dengan tag <pageNumber>.
<pageGraphics>
<setFont name="Courier" size="8"/>
<drawString x="30" y="20">Halaman <pageNumber/></drawString>
</pageGraphics>

Karena kita punya akses ke modul time, maka kita bisa gunakan:
<para style="Standard">[[ time.asctime() ]]<br/><br/></para>

User yang menjalankan report bisa diakses dengan cara berikut (perhatikanlah bahwa ini adalah object
user OpenERP):
<para style="Standard">[[ user.name ]]<br/><br/></para>

Berikut adalah parser kita, yang disimpan dalam file buku_partner_nop_14_report.py:


import random

124/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


from openerp.report import report_sxw
class buku_partner_nop_14(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(buku_partner_nop_14, self).__init__(cr, uid, name, context=context)
self.localcontext.update(
{
'random': random,
}
)
report_sxw.report_sxw('report.buku.partner.nop.14', 'res.partner',
'addons/buku_partner_nop_14/report.rml',
parser=buku_partner_nop_14)

Dalam constructor class yang diturunkan dari rml_parse, kita memanggil constructor parent dan
mengupdate localcontext. Akses untuk modul random kita berikan dengan key 'random'. Kita bisa
gunakan dalam report:
<para style="Standard">[[ random.random() ]]<br/><br/></para>

Tidak lupa, kita instansiasi class report_sxw dari modul report_sxw, dengan informasi laporan kita,
termasuk parser yang digunakan.
Dalam contoh yang lebih umum, kita bisa tambahkan method dalam class parser, yang kemudian
ditambahkan cara akses pada localcontext sehingga bisa dipanggil dari dalam report.

Berikut adalah isi file __openerp__.py:


{
'name': 'Partner 14',
'version': '1.0',
'author': 'noprianto',
'description': 'partner, laporan (dengan parser)',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': ['buku_partner_nop_14_report.xml'],
}

Berikut adalah isi file __init__.py:


from . import buku_partner_nop_14_report

125/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

126/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

7.6 Wizard
Dalam contoh modul buku_nop_report_1, kita bekerja pada model res.partner dan akan menambahkan
satu report.
Report akan diakses lewat menuitem tersendiri. Hasil dari report adalah daftar partner dengan nama
mengandung karakter tertentu. Untuk kebutuhan ini, kita tidak perlu memilih satu atau lebih record,
karena justru yang ingin kita lakukan adalah mencari.
Kriteria pencarian dapat diinput pada wizard.
Ini merupakan contoh sederhana, namun dapat dikembangkan lebih lanjut.

Berikut adalah definisi report selengkapnya (buku_nop_report_1_report.xml):


<?xml version="1.0"?>
<openerp>
<data>
<report
id="report_buku_nop_report_1"
name="buku.nop.report.1"

127/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


string="Buku Report 1"
model="res.partner"
rml="buku_nop_report_1/report.rml"
auto="False"
header="False"/>
</data>
</openerp>

Laporan sendiri akan dihasilkan dari file report.rml:


<?xml version="1.0"?>
<document filename="report.pdf">
<template pageSize="(612, 792)" title="Report">
<pageTemplate id="page">
<frame id="page" x1="30.0" y1="30.0" width="552" height="732"/>
<pageGraphics>
<setFont name="Courier" size="8"/>
<drawString x="30" y="20">Halaman <pageNumber/></drawString>
</pageGraphics>
</pageTemplate>
</template>
<stylesheet>
<blockTableStyle id="Table">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
<lineStyle kind="GRID" colorName="#000000" start="0,0" stop="-1,-1"/>
</blockTableStyle>
<paraStyle name="Standard" fontName="Courier"/>
</stylesheet>
<story>
<para style="Standard">Buku Report 1<br/><br/></para>
<para style="Standard">Nama mengandung teks: [[ data.get('form',
{}).get('name') ]]<br/><br/></para>
<blockTable colWidths="100,200,252" repeatRows="1" style="Table">
<tr>
<td>
<para style="Standard">ID</para>
</td>
<td>
<para style="Standard">Nama</para>
</td>
<td>
<para style="Standard">Website</para>
</td>
</tr>
<tr>
<td>

128/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<para style="Standard">[[
<para style="Standard">[[
</td>
<td>
<para style="Standard">[[
</td>
<td>
<para style="Standard">[[
</td>
</tr>
</blockTable>
</story>

repeatIn(objects, 'o') ]]</para>


o.id ]]</para>
o.name ]]</para>
o.website ]]</para>

</document>

Kriteria pencarian yang diinput oleh user lewat wizard dapat kita akses dengan cara berikut. Variabel
data merupakan sebuah dictionary, mengandung key 'form', yang juga merupakan sebuah dictionary,
mengandung key 'name' berisi apa yang diinput oleh user.
<para
style="Standard">Nama
mengandung
{}).get('name') ]]<br/><br/></para>

teks:

[[

data.get('form',

Berikut adalah parser kita, yang disimpan dalam file buku_nop_report_1_report.py:


from openerp.report import report_sxw
class buku_nop_report_1(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(buku_nop_report_1, self).__init__(cr, uid, name, context=context)
report_sxw.report_sxw('report.buku.nop.report.1', 'res.partner',
'addons/buku_nop_report_1/report.rml',
parser=buku_nop_report_1)

Karena kita bekerja dengan wizard, kita perlu membuatnya terlebih dahulu, dalam bentuk sebuah class,
yang diturunkan dari orm.TransientModel. Berikut adalah isi file buku_nop_report_1_wizard.py:
from openerp.osv import orm, fields
class buku_nop_report_1(orm.TransientModel):
_name = 'buku.nop.report.1'
_description = 'buku nop report 1 wizard'
_columns = {

129/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


'name': fields.char('Nama mengandung teks', size=64),
}
def _get_data(self, cr, uid, ids, context=None):
ret = {}
res = self.read(cr, uid, ids, context=context)
if res:
ret = res[0]
return ret
def download_pdf(self, cr, uid, ids, context=None):
data = self._get_data(cr, uid, ids, context=context)
domain = [('name', 'ilike', data.get('name'))]
search_result = self.pool.get('res.partner').search(cr, uid, domain)
datas = {
'ids': search_result,
'model': 'res.partner',
'form': data,
}
ret = {
'type': 'ir.actions.report.xml',
'report_name': self._name,
'datas': datas,
}
return ret

Catatan:
Wizard kita akan berisikan satu field, yaitu name (bertipe char). Kita akan gunakan ini sebagai
kriteria pencarian sebelum menghasilkan report.
Fungsi _get_data digunakan untuk mendapatkan input dari user, menggunakan method read.
Ingatlah bahwa kita berada dalam model buku.nop.report.1 ketika kita melakukan read. Dengan ids
yang kita lewatkan, kita akan mendapatkan anggota pertama dari list yang dikembalikan. Apabila
diperlukan, bacalah juga contoh fungsi read dalam Bab 4.
Yang sangat menarik adalah fungsi download_pdf. Nama ini bukan nama baku, dan diasosiasikan
dengan sebuah tombol di view.
Di dalam fungsi download_pdf, setelah mendapatkan informasi apa yang diinput oleh user, kita
lakukan pencarian:
data = self._get_data(cr, uid, ids, context=context)
domain = [('name', 'ilike', data.get('name'))]
search_result = self.pool.get('res.partner').search(cr, uid, domain)

130/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Hasil pencarian, kita tempatkan pada sebuah dictionary dengan key adalah ids:
datas = {
'ids': search_result,

Kita bekerja dengan model res.partner:


'model': 'res.partner',

Dan, apa yang diinput oleh user bisa diakses dengan key form, sebagaimana kita lihat dalam file
RML:
'form': data,
}

Fungsi akan mengembalikan satu dictionary dengan key memiliki arti khusus. Sebagai contoh, key
datas dapat diakses dari dalam report sebagai variabel data.
'datas': datas,

<para
style="Standard">Nama
mengandung
{}).get('name') ]]<br/><br/></para>

teks:

[[

data.get('form',

Kita memberitahu OpenERP bahwa kita ingin menghasilkan report. Perhatikanlah key type berikut.
'type': 'ir.actions.report.xml',
'report_name': self._name,

Kita bisa menggunakan kursor koneksi database (variabel cr) untuk melakukan SQL Query,
langsung pada database.

Bagaimana wizard ditampilkan, kita definisikan dalam view buku_nop_report_1_view.xml:


<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="buku_nop_report_1_form">
<field name="name">buku.nop.report.1</field>
<field name="model">buku.nop.report.1</field>
<field name="arch" type="xml">
<form string="Buku Report 1">
<group>
<field name="name"/>
<button

131/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


name="download_pdf"
type="object"
string="PDF"
class="oe_highlight"/>
<button string="Cancel" special="cancel"/>
</group>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="action_buku_nop_report_1">
<field name="name">Report 1</field>
<field name="res_model">buku.nop.report.1</field>
<field name="view_id" ref="buku_nop_report_1_form"/>
<field name="target">new</field>
</record>
<menuitem name="Buku" id="menu_buku"/>
<menuitem name="Report" id="menu_buku_report" parent="menu_buku"/>
<menuitem name="Buku Report 1" id="menu_buku_report_nop_report_1"
parent="menu_buku_report" action="action_buku_nop_report_1"/>
</data>
</openerp>

Perhatikanlah bahwa kita mendefinisikan tombol PDF dengan cara berikut:


<button
name="download_pdf"
type="object"
string="PDF"
class="oe_highlight"/>

dimana fungsi akan menjalankan fungsi download_pdf (name) ketika diklik (type object). Tombol
cancel merupakan tombol khusus:
<button string="Cancel" special="cancel"/>

Berikut adalah isi file __openerp__.py:


{
'name': 'Report 1',
'version': '1.0',
'author': 'noprianto',
'description': 'Laporan dengan wizard',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
'data': [

132/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


'buku_nop_report_1_view.xml',
'buku_nop_report_1_report.xml',
],
}

Berikut adalah isi file __init__.py:


from . import buku_nop_report_1_report
from . import buku_nop_report_1_wizard

133/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

8. Tip dan Trik


Penulis: Noprianto

8.1 Pelajarilah source code OpenERP


Melengkapi dokumentasi yang telah disediakan, apabila diperlukan, kita selalu dapat mempelajari
source code OpenERP, pada bagian tertentu yang kita ingin tahu lebih lanjut.
Sebagai contoh, kita akan menjalankan server OpenERP dari source code:
$ ls
debian
doc
install

LICENSE
MANIFEST.in
openerp

openerp.egg-info
openerp-server
PKG-INFO

README
setup.cfg
setup.nsi

setup.py
setup_rpm.sh
win32

Mari kita fokus pada subdirektori openerp:


$ ls openerp
addons
cli
conf
exceptions.py

import_xml.rng
__init__.py
loglevels.py
modules

netsvc.py
osv
PKG-INFO
pooler.py

release.py
report
service
sql_db.py

tests
tools
workflow

Perhatikanlah bahwa ini adalah package Python dan kita bisa menemukan apa yang kita seringkali
gunakan seperti package osv:
$ ls openerp/osv/
expression.py fields.py

__init__.py

orm.py

osv.py

query.py

Sebagaimana yang kita lakukan dalam import:


$ PYTHONPATH=./openerp python
Python 2.7.6 (default, Mar 22 2014, 22:59:38)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from openerp.osv import orm, fields
>>>

Dengan demikian, apabila kita ingin tahu lebih lanjut tentang ORM misalnya, kita dapat membaca file
openerp/osv/orm.py.
Lebih lanjut, dalam mengembangkan modul OpenERP kita sendiri, kita umumnya bergantung pada
addon base. Mari kita perhatikan subdirektori openerp/addons:
$ ls openerp/addons/base
base_data.xml base.sql

i18n

module

134/232

res

static

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


base_demo.xml
base_menu.xml

currency_data.xml
data

__init__.py
ir

__openerp__.py
report

rng
security

test
tests

Apabila kita ingin mengetahui lebih banyak tentang model res.partner misalnya, kita dapat pula
membacanya dari file openerp/addons/base/res/res_partner.py.
Mempelajari source code program sebesar OpenERP tentu saja tidak mudah. Oleh karena itu, kita
umumnya harus fokus pada bagian tertentu dulu. Walaupun ini juga tidak mudah, kita selalu bisa
mencoba/memulai dari yang paling sederhana dulu. Begitu kita sudah lebih terbiasa, proses ini akan
terasa lebih cepat dan nyaman.
Selain dokumentasi yang dituliskan pada source code (termasuk komentar), seringkali kita bisa
terbantu dengan membaca isi fungsi.

135/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

8.2 Generate file konfigurasi


Ketika menjalankan server OpenERP, kita dapat meminta untuk menghasilkan template file konfigurasi
dan langsung keluar dari program.
Sebagai contoh, kita akan menjalankan server OpenERP dari source code:
$ ls
debian
doc
install

LICENSE
MANIFEST.in
openerp

openerp.egg-info
openerp-server
PKG-INFO

README
setup.cfg
setup.nsi

setup.py
setup_rpm.sh
win32

Script openerp-server dapat digunakan untuk menjalankan server.


Opsi -s dapat diberikan untuk menghasilkan file konfigurasi, yang secara default, akan disimpan pada
~/.openerp_serverrc. Sebagai contoh:
$ ./openerp-server -s
2014-08-11 19:51:35,062 4337 INFO ? openerp: OpenERP version 7.0-20140724-231255

[CTRL-C]
$ file ~/.openerp_serverrc
/home/c2/.openerp_serverrc: ASCII text

Padukanlah opsi -s dengan -c untuk menyimpan file konfigurasi yang dihasilkan pada file lain. Sebagai
contoh, kita ingin menghasilkan file konfigurasi dan menyimpannya pada file config.ini di direktori
aktif:
$ ./openerp-server -s -c config.ini
2014-08-11 19:54:54,445 4409 INFO ? openerp: OpenERP version 7.0-20140724-231255

[CTRL-C]
$ file config.ini
config.ini: ASCII text

Padukanlah lagi dengan opsi --stop-after-init agar program langsung keluar setelah menghasilkan file
konfigurasi.
$ ./openerp-server -s -c config.ini --stop-after-init
2014-08-11 19:58:22,589 4533 INFO ? openerp: OpenERP version 7.0-20140724-231255

136/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

8.3 Lebih dari satu lokasi addons


Seringkali, kita ingin mengumpulkan semua addons yang kita bangun pada direktori tersendiri, dan
tidak bercampur dengan addons yang datang bersama OpenERP ataupun pihak lainnya.
Ini juga akan sangat membantu ketika dalam proses pengembangan, dimana kita tidak perlu selalu
mengopikan apa yang kita bangun ke direktori addons tertentu agar dapat dikenal oleh OpenERP.
Sebagai contoh, kita akan menjalankan server OpenERP dari source code:
$ ls
debian
doc
install

LICENSE
MANIFEST.in
openerp

openerp.egg-info
openerp-server
PKG-INFO

README
setup.cfg
setup.nsi

setup.py
setup_rpm.sh
win32

Direktori addons secara default adalah:


$ ls -1 openerp/addons/ | head -n5
account
account_accountant
account_analytic_analysis
account_analytic_default
account_analytic_plans
Untuk menginformasikan lokasi addons, kita bisa menggunakan salah satu dari dua cara berikut:
File konfigurasi: variabel addons_path, atau
Opsi ketika menjalankan server OpenERP: opsi --addons-path
Lokasi-lokasi
addons
diberikan
/path/addons/1,/path/addons/2.

dengan

dipisahkan

137/232

oleh

koma.

Sebagai

contoh

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

8.4 Pustaka notation dan notasi prefix/postfix


Untuk kriteria pencarian pada OpenERP (pengembangan), notasi yang dipergunakan adalah Polish
notation, yang dikenal juga dengan prefix notation (notasi prefix). Pada notasi ini, operator ditempatkan
di depan/kiri operan.
Sebagai contoh pada notasi infix:
1+2
Akan dituliskan sebagai berikut pada notasi prefix:
+12
Berbeda pula apabila dituliskan pada notasi postfix:
12+
Dengan notasi prefix/postfix, kita tidak perlu menggunakan kurung untuk pengelompokan.
Sebagai contoh pada OpenERP, kita akan mencari dari res.partner, untuk:
nama yang mengandung 'tes' (tidak case-sensitive) atau untuk id < 3
dan
website = ''
Perhatikanlah bahwa karena menggunakan Polish Notation, maka operator or '|' dan and '&'
ditempatkan di depan.
Pertama-tama, kita menyusun untuk kriteria pertama (or):
'|', ('name', 'ilike', 'tes'), ('id', '<', 3)

Setelah itu, kita gabungkan dengan kriteria kedua (and):


'&', '|', ('name', 'ilike', 'tes'), ('id', '<', 3), ('website', '=', '')

Dan, kita tempatkan pada sebuah list:


['&', '|', ('name', 'ilike', 'tes'), ('id', '<', 3), ('website', '=', '')]

Bagi yang tertarik lebih lanjut dengan notati prefix secara umum (tidak spesifik OpenERP), kita bisa
pula mempergunakan pustaka notation, yang dikembangkan oleh Noprianto, salah satu anggota tim
penulis buku ini, dan dapat didownload dari https://github.com/nopri/notation. Pustaka ini hanya
berisikan satu file, yaitu notation.py. Pada saat buku ini ditulis, versi pustaka adalah 0.01.
138/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Pustaka notation berisikan evaluator sederhana untuk notasi prefix dan postfix. Tersedia fungsi bantu
dan sebuah class yang dapat diturunkan.
Contoh sederhana menggunakan fungsi bantu untuk notasi prefix:
>>> import notation
>>> notation.simple_prefix_notation('+ 1 2')
3.0
>>> notation.simple_prefix_notation('* + 1 2 3')
9.0
>>> notation.simple_prefix_notation('- * + 1 2 3 4')
5.0
>>> notation.simple_prefix_notation('** - * + 1 2 3 4 5')
3125.0
>>> notation.simple_prefix_notation('/ ** - * + 1 2 3 4 5 6')
520.8333333333334
>>>

Contoh sederhana menggunakan fungsi bantu untuk notasi postfix:


>>> notation.simple_postfix_notation('1
3.0
>>> notation.simple_postfix_notation('1
9.0
>>> notation.simple_postfix_notation('1
5.0
>>> notation.simple_postfix_notation('1
3125.0
>>> notation.simple_postfix_notation('1
520.8333333333334
>>>

2 +')
2 + 3 *')
2 + 3 * 4 -')
2 + 3 * 4 - 5 **')
2 + 3 * 4 - 5 ** 6 /')

Apabila kita ingin mengurangi, menambahkan atau mengubah operator, kita bisa menurunkan dari
class SimplePrefixPostfixNotation. Pada contoh pertama, kita hanya mengenal operator +.
>>> import operator
>>> from notation import SimplePrefixPostfixNotation
>>>
>>> class LimitedPrefixPostfixNotation(SimplePrefixPostfixNotation):
...
def __init__(self, reverse=False):
...
self.OPERATORS = {'+': operator.add}
...
self.reverse = reverse
...
>>>
>>> o = LimitedPrefixPostfixNotation()
>>> print o.evaluate('+ 1 2')
3.0
>>> print o.evaluate('* + 1 2 3')
None
>>>

139/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Pada contoh kedua, kita menggunakan karakter 'x' (bukan '*') sebagai operator kali.
>>> class AnotherPrefixPostfixNotation(SimplePrefixPostfixNotation):
...
def __init__(self, reverse=False):
...
SimplePrefixPostfixNotation.__init__(self, reverse)
...
self.OPERATORS.pop('*')
...
self.OPERATORS['x'] = operator.mul
...
>>>
>>> o = AnotherPrefixPostfixNotation()
>>> print o.evaluate('+ 1 2')
3.0
>>> print o.evaluate('* + 1 2 3')
None
>>> print o.evaluate('x + 1 2 3')
9.0
>>>
'''

Dalam pustaka notation ini, evaluator diimplementasikan menggunakan stack, dimana list
dipergunakan sebagai stack. Untuk prefix, ekspresi akan diproses dari belakang.
Berikut adalah cuplikan fungsi evaluate0 class SimplePrefixPostfixNotation. Apabila reverse adalah
True, maka dimaksudkan adalah notasi postfix.
def evaluate0(self, expression):
stack = []
e = str(expression).split()
if not self.reverse:
e = e[-1::-1]
for i in e:
if i not in self.OPERATORS.keys():
n = float(i)
# ValueError
if not self.reverse:
stack.append(n)
else:
stack.insert(0, n)
else:
o1 = stack.pop() #IndexError
o2 = stack.pop() #IndexError
res = self.OPERATORS.get(i)(o1, o2)
if not self.reverse:
stack.append(res)
else:
stack.insert(0, res)
return stack

140/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Fungsi evaluate hanya membantu saja:
def evaluate(self, expression):
res = None
try:
res = self.evaluate0(expression)
if not len(res) == 1:
raise Exception
res = res[0]
except:
pass
return res

Constructor class:
def __init__(self, reverse=False):
self.OPERATORS = {
'+': operator.add,
'-': operator.sub,
'/': operator.truediv,
'*': operator.mul,
'%': operator.mod,
'**': operator.pow,
}
self.reverse = reverse

Dan, fungsi-fungsi bantu diimplementasikan dengan cara:


def simple_prefix_notation(expression):
o = SimplePrefixPostfixNotation()
return o.evaluate(expression)
def simple_postfix_notation(expression):
o = SimplePrefixPostfixNotation(reverse=True)
return o.evaluate(expression)

141/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

8.5 Lisensi pada modul OpenERP


Ketika kita mengembangkan suatu modul OpenERP, kita dapat menentukan string lisensi dalam file
manifest __openerp__.py. Sebagai contoh:
{
'name': 'Test',
'version': '1.0',
'license': 'GPL',
'author': 'noprianto',
'description': 'Test',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
}

Ketika melakukan update module list, terdapat pesan kesalahan ValidateError sebagai berikut:
The value "GPL" for the field "ir_module_module.license" is not in the selection
Apabila kita ubah license menjadi sesuatu yang lain, misal Public Domain:
{
'name': 'Test',
'version': '1.0',
'license': 'Public Domain',
'author': 'noprianto',
'description': 'Test',
'category': 'Buku',
'website': 'https://github.com/id-python/buku-openerp',
'depends': ['base'],
}

Kita akan menjumpai pesan kesalahan serupa:


The value "Public Domain" for the field "ir_module_module.license" is not in the selection
Untuk memahami pesan kesalahan tersebut, kita perlu lihat ke
openerp/addons/base/module/module.py, dimana license didefinisikan sebagai berikut:

dalam

'license': fields.selection([
('GPL-2', 'GPL Version 2'),
('GPL-2 or any later version', 'GPL-2 or later version'),
('GPL-3', 'GPL Version 3'),
('GPL-3 or any later version', 'GPL-3 or later version'),
('AGPL-3', 'Affero GPL-3'),
('Other OSI approved licence', 'Other OSI Approved Licence'),

142/232

file

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


('Other proprietary', 'Other Proprietary')
], string='License', readonly=True),

Sehingga, salah satu pilihan yang bisa kita lakukan adalah mengubah string lisensi ke yang dikenal.

143/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

8.6 Perubahan pada file python dalam modul


Dalam pengembangan, apabila kita melakukan perubahan pada file python (.py) dalam modul
(termasuk upgrade), kita dapat melakukan restart server OpenERP agar perubahan yang dilakukan
dapat berefek.

8.7 Menampilkan pesan kesalahan


Walaupun kita bisa menggunakan atribut _constraints untuk membantu memastikan nilai input adalah
valid, ada kalanya kita ingin menampilkan pesan kesalahan sendiri.
Untuk kebutuhan tersebut, kita bisa membangkitkan exception except_orm yang didefinisikan di dalam
modul orm.py:
class except_orm(Exception):
def __init__(self, name, value):
self.name = name
self.value = value
self.args = (name, value)

Sebelumnya, kita akan import _ dari openerp.tools.translate.


from openerp.tools.translate import _

Dan, exception bisa dibangkitkan seperti contoh berikut:


>>> from openerp.osv import orm
>>> from openerp.tools.translate import _
>>>
>>> raise orm.except_orm(_('Judul'), _('Pesan Kesalahan'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
openerp.osv.orm.except_orm: ('Judul', 'Pesan Kesalahan')

144/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

8.8 Format tanggal/waktu


Apabila kita perlu melakukan format atau parsing tanggal/waktu, kita dapat mempergunakan konstanta
berikut, yang didefinisikan di dalam file openerp/tools/misc.py.
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
DEFAULT_SERVER_TIME_FORMAT = "%H:%M:%S"
DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
DEFAULT_SERVER_DATE_FORMAT,
DEFAULT_SERVER_TIME_FORMAT)

File misc.py tersebut diimport oleh __init__.py:


from misc import *

Contoh:
>>> from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
>>> from openerp.tools import DEFAULT_SERVER_TIME_FORMAT
>>> from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
>>>
>>> DEFAULT_SERVER_DATE_FORMAT
'%Y-%m-%d'
>>> DEFAULT_SERVER_TIME_FORMAT
'%H:%M:%S'
>>> DEFAULT_SERVER_DATETIME_FORMAT
'%Y-%m-%d %H:%M:%S'
>>>
>>> import time
>>> time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
'2014-08-15 19:03:20'
>>> time.strptime('2014-08-15', DEFAULT_SERVER_DATE_FORMAT)
time.struct_time(tm_year=2014, tm_mon=8, tm_mday=15, tm_hour=0, tm_min=0, tm_sec=0,
tm_wday=4, tm_yday=227, tm_isdst=-1)
>>>

145/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9. Web Service dengan XML-RPC


Penulis: Noprianto

9.1 ERP dan sistem berjalan


Dalam implementasi sebuah ERP, umum ditemukan perusahaan telah memiliki sistem yang berjalan
sebelumnya. Sistem tersebut, walaupun mungkin lebih sederhana ataupun kurang terintegrasi, biasanya
telah terbiasa digunakan.
Dan, tak jarang, proses transisi ke sebuah ERP membutuhkan dua sistem berjalan berdampingan.
Idealnya, sistem lama secara bertahap perlu dikurangi. Tapi, kondisi di lapangan bisa sangat bervariasi.
Kadang-kadang, terdapat resistensi yang cukup tinggi dari sisi user. Permasalahannya, semakin lama
perusahaan menjalankan dua sistem, semakin jauh pula implementasi sebuah ERP bisa sukses,
terutama kalau terdapat perbedaan antar sistem yang fundamental.
Salah satu strategi yang dapat dilakukan adalah dengan konversi data dari sistem lama ke sistem baru,
yang dilakukan secara bertahap. Ini dilakukan sambil pelatihan ERP dilakukan kepada user. Strategi ini
dapat kita lakukan apabila sistem yang saat ini berjalan sudah tidak dapat dimodifikasi lagi, misal
karena source code program tidak tersedia.
Tapi, mari bayangkan situasi dimana sistem berjalan dikembangkan sendiri oleh tim IT internal. Para
pengembangnya masih bekerja di perusahaan dan modifikasi bisa dilakukan dengan relatif cepat. Yang
ingin kita lakukan adalah ketika data entri dilakukan, langsung disimpan pada server OpenERP.
Apabila terdapat laporan sederhana, secara bertahap, juga dapat diambil dari server OpenERP. User
interfacenya bisa tetap sama (atau dengan sedikit penyesuaian).
Kita mengetahui bahwa OpenERP menggunakan database system PostgreSQL. Dan, pustaka untuk
bekerja dengan database ini tersedia untuk banyak bahasa pemrograman. Jadi, kita mungkin bisa
menulis/membaca langsung pada database server-nya. Tentang skema data, karena ini terbuka, maka
kita bisa pelajari.
Tapi, coba pikirkan lebih lanjut beberapa pertimbangan berikut:
Akses langsung pada database PostgreSQL mungkin tidak diberikan. Untuk alasan keamanan,
umumnya, database server hanya mengijinkan akses dari OpenERP server.
Kita perlu mempelajari skema yang digunakan. Dengan ratusan tabel dan relasi diantara mereka, ini
bukan pekerjaan mudah.
Yang paling penting: dengan arsitektur OpenERP, akses langsung pada database tidak disarankan.
Sebagai gantinya, OpenERP menyediakan web service yang akan jauh lebih mudah, nyaman dan
aman untuk digunakan.

146/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.2 Membangun frontend sendiri


Bagi Anda yang tidak perlu mengalami permasalahan yang dibahas sebelumnya, mari kita anggap Anda
cukup beruntung.
Tapi, setelah implementasi tahap awal dilakukan, manajemen mungkin beranggapan bahwa user
interface OpenERP tidak selalu cocok digunakan untuk semua user. Sebagai contoh, user di
divisi/departemen tertentu akan dapat bekerja lebih cepat apabila sepenuhnya menggunakan keyboard.
Tanpa mouse, tanpa GUI, hanya berbasis teks saja.
Lebih lanjut lagi, rupanya terdapat sebagian user yang ingin mengakses ERP lewat perangkat mobile
(untuk sebagian kecil fitur). Walaupun akses langsung pada user interface OpenERP (misal lewat VPN)
secara teknis dapat dilakukan, manajemen mungkin lebih memilih untuk membangun sistem terpisah,
yang tetap terintegrasi dengan OpenERP. Sistem terpisah tersebut yang akan melayani permintaan dari
perangkat mobile.
Atau, terdapat contoh kasus lain, dimana input data dilakukan secara otomatis, terus menerus, secara
realtime. Data didapatkan dari komputer yang terhubung pada perangkat keras tertentu.
Seberapa jauh Anda perlu atau ingin membangun frontend atau sistem sendiri yang tetap terhubung ke
OpenERP, akses langsung pada database seperti disinggung sebelumnya tetap tidak disarankan. Dan,
kita akan selalu mengandalkan web service yang telah disediakan.

147/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.3 XML-RPC dan Python


Terdapat beberapa protokol web service yang disediakan oleh OpenERP, namun bab ini hanya akan
membahas XML-RPC. Protokol ini memungkinkan Remote Procedure Call (RPC) yang:
menggunakan XML untuk mengencode pemanggilan
menggunakan HTTP sebagai mekanisme transport
Protokol ini dikembangkan pada tahun 1998. Pustaka untuk berbagai bahasa pemrograman juga mudah
ditemukan.
Khusus untuk Python, pustaka untuk bekerja dengan XML-RPC (client ataupun server) telah disertakan
dalam standard library sejak Python versi 2.2. Dalam tulisan ini, kita hanya akan menggunakan pustaka
client yaitu xmlrpclib pada Python 2.x.
Terdapat sejumlah fungsi yang disediakan oleh OpenERP. Kita akan membahas sebagian dari fungsifungsi tersebut dari perspektif Python, baik dengan memanfaatkan pustaka bantu ataupun langsung
menggunakan xmlrpclib.
Untuk contoh XML-RPC dan OpenERP dengan beberapa bahasa pemrograman lain, Anda dapat
membacanya dari dokumentasi resmi OpenERP.

148/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.4 Pustaka oerpapi


Pada dasarnya, kita cukup menggunakan xmlrpclib untuk berbicara dengan server OpenERP. Namun,
beberapa pustaka bantu membuatnya lebih mudah dan nyaman. Salah satu pustaka yang dapat
digunakan adalah oerpapi.
Pustaka ini dikembangkan oleh Noprianto, salah satu anggota tim penulis buku ini, dan dapat
didownload dari https://github.com/nopri/oerpapi. Lisensi yang dipergunakan adalah LGPL, sehingga
aplikasi yang menggunakan pustaka ini tidak harus disediakan source codenya. Sebagai catatan,
pustaka oerpapi pada saat tulisan ini dibuat masih relatif baru dan berada pada versi 0.03.
Semua class ataupun fungsi akan selalu tersedia dalam satu file tunggal oerpapi.py. File ini dapat
dikopikan pada (salah satu):
Direktori pustaka Python yang terdaftar (system-wide)
Direktori lain, dimana Anda perlu mengatur environment variabel PYTHONPATH
Direktori program Anda (atau subdirektori di dalamnya)
Untuk menggunakan pustaka ini, kita dapat melakukan import seperti contoh berikut:
import oerpapi

Beberapa class telah disediakan untuk bekerja dengan OpenERP. Kita akan membahas beberapa contoh
di sini. Pembahasan lain dapat pula ditemukan pada contoh-contoh program. Sementara, untuk
informasi selengkapnya tentang module ini, rujuklah pada source code oerpapi.py.

OErpClient
Kita umumnya selalu mulai dari menginstansiasi class ini. Contoh:
>>> client = oerpapi.OErpClient('localhost')
>>> client
<oerpapi.OErpClient instance at 0xb726ec8c>

Untuk terhubung ke server, kita menggunakan method connect(). Contoh:


>>> client.connect()

Setelah terhubung, kita bisa mendapatkan beberapa informasi dari server seperti contoh berikut:
>>> client.version()
{'server_version_info': [7, 0, 0, 'final', 0], 'server_serie': '7.0',
'server_version': '7.0-20140724-231255', 'protocol_version': 1}

>>> print client.server_environment()

149/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Environment Information :
System : Linux-3.13.0-24-generic-i686-with-Ubuntu-14.04-trusty
OS Name : posix
Distributor ID:
Ubuntu
Description:
Ubuntu 14.04 LTS
Release:
14.04
Codename:
trusty
Operating System Release : 3.13.0-24-generic
Operating System Version : #46-Ubuntu SMP Thu Apr 10 19:08:14 UTC 2014
Operating System Architecture : 32bit
Operating System Locale : en_US.UTF-8
Python Version : 2.7.6
OpenERP-Server Version : 7.0-20140724-231255

Sebelum bekerja dengan database, kita perlu melakukan login terlebih dahulu:
>>> client.login('test1', 'demo', 'demo')
>>> client.uid
3

Informasi class
class OErpClient
| __init__(self, host, port=8069, data=None)
|
| check_connectivity(self)
|
| connect(self, **args)
|
| create_url(self, resource)
|
| get_db(self)
|
| get_model(self, model)
|
| get_report(self, model, ids, datas=False, context=False)
|
| login(self, database, user, password)
|
| server_environment(self)
|
| version(self)

OErpModel
Melanjutkan dari contoh sebelumnya, ketika telah terhubung dan login, kita bisa bekerja dengan model
OpenERP, sebagai contoh adalah res.partner:
>>> partner = client.get_model('res.partner')
>>> partner
<oerpapi.OErpModel instance at 0xb710e62c>

Terdapat beberapa method yang telah disediakan seperti:


150/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

create: membuat. Catatan: pastikan semua field yang required telah diisikan.
write: update
read: membaca. Catatan: gunakan list kosong sebagai field untuk mendapatkan semua field.
search: mencari. Catatan: untuk kriteria lebih dari satu, pencarian dilakukan dengan Polish
Notation, dimana operator seperti '|' dan '&' ditempatkan di depan.
unlink: menghapus

Contoh:
>>> partner_id = partner.create({'name': 'test'})
>>> partner_id
122
>>> partner.write(partner_id, {'name': 'test baru'})
True
>>> partner_search = partner.search([('name', 'ilike', 'test')])
>>> print partner_search
[119, 121, 122]
>>> partner.read(partner_search, ['name'])
[{'name': 'Test 123', 'id': 119}, {'name': 'test 1234', 'id': 121}, {'name': 'test
baru', 'id': 122}]
>>> partner.unlink(partner_id)
True

Informasi class
class OErpModel
| __init__(self, client, model)
|
| check_context(self, context)
|
| check_fields(self, fields)
|
| check_ids(self, ids)
|
| check_none(self, val, default=False)
|
| create(self, values, context=None)
|
| read(self, ids, fields=None, context=None)
|
| search(self, domain, offset=0, limit=None, order=None, context=None,
count=False)
|
| unlink(self, ids, context=None)
|
| write(self, ids, values, context=None)

151/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

OErpDb
Dari instance OErpClient, kita bisa pula bekerja dengan database:
>>> db = client.get_db()
>>> db
<oerpapi.OErpDb instance at 0xb710e46c>

Terdapat beberapa method yang telah disediakan seperti:


list: mendapatkan daftar database yang tersedia
list_lang: mendapatkan daftar bahasa
exist: memeriksa apakah suatu database telah ditemukan
create: membuat database baru. Bahasa yang dipergunakan bisa diatur, namun tidak semua
terjemahan telah lengkap. Password yang dilewatkan pada fungsi ini akan menjadi password admin
untuk database yang dibuat.
drop: menghapus database
rename: mengganti nama database
dump: melakukan dump/backup database ke file. Perhatikanlah bahwa nilai yang dikembalikan
adalah dalam encoding base64.
restore: melakukan restore dari file ke database baru. Sebagaimana halnya pada dump, kita perlu
melewatkan dalam encoding base64.
duplicate: membuat database baru berdasarkan database yang ada
change_admin_password: mengganti password admin. Apa yang kita ganti di sini akan ditulis ulang
pada file konfigurasi server (bukan hanya berlaku sementara).
Contoh:
>>> db.list()
['test1', 'test1_copy', 'test2', 'test3', 'test3_new', 'test_baru', 'test_baru2']
>>> db.exist('database_tidak_ditemukan')
False
>>> db.exist('test1')
True

Untuk tugas-tugas administratif, kita perlu menyediakan password admin, seperti yang ditentukan pada
konfigurasi server OpenERP:
>>> db.admin_password = 'myadminpassword'

Contoh tugas-tugas administratif:


>>> db.create('test_create', False, 'en_US', 'mypassword')
True

152/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> db.rename('test_create', 'test_create_rename')
True
>>> db.duplicate('test_create_rename', 'test_duplicate')
True
>>> db.drop('test_create')
False
>>> db.drop('test_create_rename')
True
>>> db.drop('test_duplicate')
True

Perhatikanlah bahwa apabila password admin tidak diberikan, maka exception akan terjadi:
>>> db.admin_password = ''
>>> db.create('test_create', False, 'en_US', 'mypassword')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>

raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault AccessDenied: 'Access denied.'>

Informasi class
class OErpDb
| __init__(self, client)
|
| change_admin_password(self, new_password)
|
| create(self, name, demo, lang, password)
|
| drop(self, name)
|
| dump(self, name)
|
| duplicate(self, name, target_name)
|
| exist(self, name)
|
| list(self, arg=False)
|
| list_lang(self)
|
| rename(self, name, new_name)
|
| restore(self, name, data)

153/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

OErpReport
Melanjutkan dari contoh sebelumnya, ketika telah terhubung dan login, kita bisa bekerja dengan report
OpenERP. Sebagai contoh, kita bekerja dengan model res.partner:
>>> client.login('test1', 'demo', 'demo')
>>> partner = client.get_model('res.partner')
>>> partner_search = partner.search([('name', 'ilike', 'test')])
>>> report = client.get_report('res.partner', partner_search)
>>> report
<oerpapi.OErpReport instance at 0xb705deec>

Report dalam format PDF bisa didapatkan dengan cara memanggil method get. Sebagai contoh:
>>> report_output = report.get()

Apa yang dihasilkan adalah isi file report dalam encoding base64. Kita dapat menulisnya ke file:
>>> import base64
>>> if report_output:
...
f = open('/tmp/report.pdf', 'wb')
...
f.write(base64.decodestring(report_output))
...
f.close()
...

Menggunakan program 'file', kita bisa memastikan bahwa file yang dihasilkan adalah dalam format
PDF:
$ file report.pdf
report.pdf: PDF document, version 1.4

Untuk pengaturan report lebih lanjut, kita bisa melewatkan datas dan context sebagai argumen ketiga
dan keempat pada get_report(). Untuk informasi lebih lanjut tentang report, bacalah juga Bab 7
Laporan.
Penundaan dilakukan selama beberapa waktu tertentu sampai report berhasil dibuat. Rujuklah ke
source code untuk OErpReport untuk delay_1, delay_2 dan number_of_tries. Kita akan membahas ini
juga pada contoh program laporan (11.8).
Informasi class
class OErpReport
| __init__(self, client, model, ids, datas=False, context=False)
|
| check_datas(self)
|
| get(self)

154/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Exception
Modul ini tidak melakukan try/except untuk exception yang mungkin terjadi. Sebagai contoh, ketika
kita tidak melakukan koneksi terlebih dahulu dan ingin login:
>>> client = oerpapi.OErpClient('localhost')>>> client.login('test1', 'demo',
'demo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>

self.uid = self.sock_common.login(self.database, self.user,


AttributeError: 'bool' object has no attribute 'login'

Atau, ketika kita sudah terhubung, namun belum melakukan login dan ingin melakukan pencarian:
>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()
>>>
>>> partner = client.get_model('res.partner')
>>> partner_search = partner.search([('name', 'ilike', 'test')])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>

raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault FATAL: database "False" does not exist

Oleh karena itu, sangat disarankan dalam program untuk memeriksa adanya exception. Contoh
sederhana ketika login dengan password yang salah:
>>> import xmlrpclib
>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()
>>>
>>> client.login('test1', 'demo', '')
>>> partner = client.get_model('res.partner')
>>>
>>> try:
...
partner_search = partner.search([('name', 'ilike', 'test')])
... except xmlrpclib.Fault, e:
...
partner_search = []
...
print 'Terjadi kesalahan: %s' %(e)
...
Terjadi kesalahan: <Fault AccessDenied: 'Access denied.'>
>>>

155/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Memeriksa hasil login


Perhatikanlah bahwa method login() tidak mengembalikan nilai sukses atau gagal. Mari kita contohkan
login dengan password yang salah:
>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()
>>>
>>> result = client.login('test1', 'demo', '')
>>> result
>>> type(result)
<type 'NoneType'>
>>>

Untuk memeriksa apakah login gagal atau sukses, akseslah property uid. Sebagai contoh, pada login
yang gagal:
>>> client.uid
False

Dan, contoh untuk login yang berhasil (uid akan berisikan nilai User ID OpenERP):
>>> client.login('test1', 'demo', 'demo')
>>> client.uid
3

Pemeriksaan berikut bisa pula digunakan:


>>> client.login('test1', 'demo', '')
>>> if client.uid:
...
print 'Login berhasil'
... else:
...
print 'Login gagal'
...
Login gagal
>>> client.login('test1', 'demo', 'demo')
>>> if client.uid:
...
print 'Login berhasil'
... else:
...
print 'Login gagal'
...
Login berhasil

156/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.5 Program: pilih dan login ke database


Pada program berikut, kita akan mendapatkan daftar database, kemudian memilih dan login ke
database. Program mempergunakan pustaka oerpapi.
Source code (11_5.py)
#
#
#
#
#
#

11_5.py
(c) Noprianto <nop@tedut.com> GPL
Mendapatkan daftar database
Memilih database
Login ke database

import oerpapi
host = raw_input('Server: ')
print 'Mencoba melakukan koneksi ke %s pada port default...' %(host)
client = oerpapi.OErpClient(host)
client.connect()
version = client.version()
print 'Versi: %s' %(version.get('server_version'))
db = client.get_db()
db_list = db.list()
print 'Database yang tersedia: %s' %(db_list)
db_name = raw_input('Database yang ingin digunakan: ')
if not db.exist(db_name):
print 'Database %s tidak ditemukan' %(db_name)
else:
user = raw_input('[%s] Masukkan nama user: ' %(db_name))
password = raw_input('[%s] Masukkan password: ' %(db_name))
print 'Mencoba login...'
client.login(db_name, user, password)
print 'UserID adalah: %s' %(client.uid)

Jalankanlah program dengan cara berikut:


$ python 11_5.py
Server: localhost
Mencoba melakukan koneksi ke localhost pada port default...
Versi: 7.0-20140724-231255
Database yang tersedia: ['test1', 'test1_copy', 'test2', 'test3', 'test3_new',
'test_baru', 'test_baru2']
Database yang ingin digunakan: test1

157/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


[test1] Masukkan nama user: demo
[test1] Masukkan password: demo
Mencoba login...
UserID adalah: 3

Contoh memilih database yang tidak ditemukan:


$ python 11_5.py
Server: localhost
Mencoba melakukan koneksi ke localhost pada port default...
Versi: 7.0-20140724-231255
Database yang tersedia: ['test1', 'test1_copy', 'test2', 'test3', 'test3_new',
'test_baru', 'test_baru2']
Database yang ingin digunakan: test
Database test tidak ditemukan

Contoh login gagal:


$ python 11_5.py
Server: localhost
Mencoba melakukan koneksi ke localhost pada port default...
Versi: 7.0-20140724-231255
Database yang tersedia: ['test1', 'test1_copy', 'test2', 'test3', 'test3_new',
'test_baru', 'test_baru2']
Database yang ingin digunakan: test1
[test1] Masukkan nama user:
[test1] Masukkan password:
Mencoba login...
UserID adalah: False

158/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.6 Program: buat, update, baca, hapus


Pada program berikut, kita akan bekerja dengan model res.partner untuk:
Membuat partner baru
Mengupdate data partner
Membaca data partner
Menghapus partner
Program mempergunakan pustaka oerpapi. Pembahasan akan dilakukan setelah source code dan contoh
output.
Source code (11_6.py)
#
#
#
#
#
#
#

11_6.py
(c) Noprianto <nop@tedut.com> GPL
Membuat partner baru
Mengupdate data partner
Menampilkan data partner
Menghapus partner

import oerpapi
host = 'localhost'
db_name = 'test1'
user = 'demo'
password = 'demo'
fields = ['name', 'website']
client = oerpapi.OErpClient(host)
client.connect()
version = client.version()
print 'Terhubung pada %s, versi %s' %(host, version.get('server_version'))
client.login(db_name, user, password)
print 'Login dengan UserID: %s' %(client.uid)
print 'Membuat partner (res.partner) baru'
partner_data = {}
for f in fields:
temp = raw_input('%s: ' %(f))
partner_data[f] = temp
partner = client.get_model('res.partner')
partner_id = partner.create(partner_data)
print 'Partner ID adalah %s' %(partner_id)
print 'Mengupdate data partner ID %s' %(partner_id)
partner_data = {}
for f in fields:

159/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


temp = raw_input('%s: ' %(f))
partner_data[f] = temp
partner.write(partner_id, partner_data)
print 'Menampilkan data partner ID %s' %(partner_id)
partner_read = partner.read(partner_id, fields)
print partner_read
if raw_input('Input Y untuk menghapus partner ID %s: ' %(partner_id)) == 'Y':
partner.unlink(partner_id)

Jalankanlah program dengan cara berikut:


$ python 11_6.py
Terhubung pada localhost, versi 7.0-20140724-231255
Login dengan UserID: 3
Membuat partner (res.partner) baru
name: Test Partner Baru
website: Partner ID adalah 123
Mengupdate data partner ID 123
name: Test Partner Baru Update
website: http://domain.tld
Menampilkan data partner ID 123
[{'website': 'http://domain.tld', 'name': 'Test Partner Baru Update', 'id': 123}]
Input Y untuk menghapus partner ID 123: Y

Penjelasan
Pada dasarnya, kita bisa bekerja dengan model lain. Model res.partner dalam hal ini hanyalah
contoh saja.
Dalam contoh ini, kita bekerja dengan database test1 dan login sebagai user demo (password:
demo).
Untuk pembuatan, update dan baca data, contoh ini hanya menggunakan field name dan website.
Sesuaikanlah field ini apabila bekerja dengan model lain.

Contoh dengan model lain


Kita akan membuat sebuah product baru. Dalam hal ini, model yang akan kita gunakan adalah
product.product.
Untuk membuat product baru, kita akan login sebagai admin. Aktifkanlah developer mode untuk
mendapatkan nama field (arahkan pointer mouse pada label field).
>>> import oerpapi
>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()

160/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>>
>>> client.login('test1', 'admin', 'test1')
>>> client.uid
1
>>>
>>> product = client.get_model('product.product')
>>> product_data = {
...
'name': 'Test Produk',
...
'categ_id': 1,
...
'type': 'service'
... }
>>> product_id = product.create(product_data)
>>> product_id
51
>>>
>>> product.read(product_id, [])
[{'warranty': 0.0, 'ean13': False, 'uos_id': False, 'list_price': 1.0, 'weight':
0.0, 'message_follower_ids': [3], 'color': 0, 'incoming_qty': 0.0, 'image': False,
'standard_price': 0.0, 'variants': False, 'price_extra': 0.0, 'mes_type': 'fixed',
'uom_id': [1, 'Unit(s)'], 'code': False, 'description_purchase': False,
'default_code': False, 'name_template': 'Test Produk', 'property_account_income':
False, 'qty_available': 0.0, 'id': 51, 'message_summary': ' ', 'uos_coeff': 1.0,
'virtual_available': 0.0, 'sale_ok': True, 'message_is_follower': True, 'categ_id':
[1, 'All products'], 'product_manager': False, 'company_id': [1, 'Your Company'],
'message_ids': [254], 'product_tmpl_id': [51, 'Test Produk'], 'state': False,
'uom_po_id': [1, 'Unit(s)'], 'pricelist_id': [], 'type': 'service', 'weight_net':
0.0, 'description': False, 'price': 0.0, 'seller_qty': 0.0, 'supplier_taxes_id':
[], 'volume': 0.0, 'outgoing_qty': 0.0, 'seller_info_id': False,
'description_sale': False, 'active': True, 'cost_method': 'standard',
'partner_ref': 'Test Produk', 'rental': False, 'seller_delay': 1, 'packaging': [],
'seller_id': False, 'image_medium': False, 'name': 'Test Produk', 'price_margin':
1.0, 'property_account_expense': False, 'image_small': False, 'lst_price': 1.0,
'taxes_id': [], 'produce_delay': 1.0, 'seller_ids': [], 'message_unread': False}]
>>>

161/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.7 Program: melakukan pencarian


Pada program berikut, kita akan mencari ke res.partner sesuai dengan kriteria pencarian. Program
mempergunakan pustaka oerpapi. Pembahasan akan dilakukan setelah source code dan contoh output.
Source code (11_7.py)
# 11_7.py
# (c) Noprianto <nop@tedut.com> GPL
#
# Mencari partner
import oerpapi
host = 'localhost'
db_name = 'test1'
user = 'demo'
password = 'demo'
client = oerpapi.OErpClient(host)
client.connect()
version = client.version()
print 'Terhubung pada %s, versi %s' %(host, version.get('server_version'))
client.login(db_name, user, password)
print 'Login dengan UserID: %s' %(client.uid)
search_name = raw_input('Mencari nama partner yang mengandung teks berikut: ')
search_data = [('name', 'ilike', search_name)]
print search_data
partner = client.get_model('res.partner')
partner_search = partner.search(search_data)
print 'Ditemukan %s partner' %(len(partner_search))
if partner_search:
fields = ['name']
partner_read = partner.read(partner_search, fields)
for i in partner_read:
print i.get('name')

Jalankanlah program dengan cara berikut:


$ python 11_7.py
Terhubung pada localhost, versi 7.0-20140724-231255
Login dengan UserID: 3
Mencari nama partner yang mengandung teks berikut: tes
[('name', 'ilike', 'tes')]
Ditemukan 4 partner
Test 123

162/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


test 1234
Test SO
Test SO

Contoh pencarian dengan hasil tidak ditemukan:


$ python 11_7.py
Terhubung pada localhost, versi 7.0-20140724-231255
Login dengan UserID: 3
Mencari nama partner yang mengandung teks berikut: tidak_ditemukan
[('name', 'ilike', 'tidak_ditemukan')]
Ditemukan 0 partner

Penjelasan
Pada dasarnya, kita bisa bekerja dengan model lain. Model res.partner dalam hal ini hanyalah
contoh saja.
Kriteria pencarian mempergunakan Polish Notation. Gunakanlah '|' untuk or dan '&' untuk and.
Contoh dengan model lain
Kita akan mencari dari product.product dengan kriteria type=service.
>>> import oerpapi
>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()
>>>
>>> client.login('test1', 'demo', 'demo')
>>> client.uid
3
>>>
>>> product = client.get_model('product.product')
>>> search_data = [('type', '=', 'service')]
>>> product_search = product.search(search_data)
>>> product_search
[50, 3, 2, 1, 51]
>>>
>>> product_read = product.read(product_search, ['name'])
>>> product_read
[{'id': 50, 'name': 'Advance'}, {'id': 3, 'name': 'On Site Assistance'}, {'id': 2,
'name': 'On Site Monitoring'}, {'id': 1, 'name': 'Service'}, {'id': 51, 'name':
'Test Produk'}]
>>>

Contoh beberapa kriteria pencarian 1


Kita akan mencari dari res.partner, untuk nama yang mengandung 'tes' (tidak case-sensitive) atau untuk
id < 3.
Perhatikanlah bahwa karena menggunakan Polish Notation, maka operator or '|' ditempatkan di depan.

163/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> import oerpapi
>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()
>>>
>>> client.login('test1', 'demo', 'demo')
>>> client.uid
3
>>>
>>> partner = client.get_model('res.partner')
>>> search_data = ['|', ('name', 'ilike', 'tes'), ('id', '<', 3)]
>>> partner_search = partner.search(search_data)
>>> partner_search
[119, 121, 124, 125, 1]
>>>
>>> partner_read = partner.read(partner_search, ['name'])
>>> partner_read
[{'name': 'Test 123', 'id': 119}, {'name': 'test 1234', 'id': 121}, {'name': 'Test
SO', 'id': 124}, {'name': 'Test SO', 'id': 125}, {'name': 'Your Company', 'id': 1}]
>>>

Contoh beberapa kriteria pencarian 2


Kita akan mencari dari res.partner, untuk:
nama yang mengandung 'tes' (tidak case-sensitive) atau untuk id < 3
dan
website = ''
Perhatikanlah bahwa karena menggunakan Polish Notation, maka operator or '|' dan and '&'
ditempatkan di depan.
Pertama-tama, kita menyusun untuk kriteria pertama (or):
'|', ('name', 'ilike', 'tes'), ('id', '<', 3)

Setelah itu, kita gabungkan dengan kriteria kedua (and):


'&', '|', ('name', 'ilike', 'tes'), ('id', '<', 3), ('website', '=', '')

>>> import oerpapi


>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()
>>>
>>> client.login('test1', 'demo', 'demo')
>>> client.uid
3
>>>
>>> partner = client.get_model('res.partner')
>>> search_data = ['&', '|', ('name', 'ilike', 'tes'), ('id', '<', 3), ('website',
'=', '')]
>>> partner_search = partner.search(search_data)

164/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> partner_search
[119]
>>> partner_read = partner.read(partner_search, ['name', 'website'])
>>> partner_read
[{'website': '', 'name': 'Test 123', 'id': 119}]
>>>
>>> search_data = ['|', ('name', 'ilike', 'tes'), ('id', '<', 3)]>>> partner_search
= partner.search(search_data)
>>> partner_search
[119, 121, 124, 125, 1]
>>>
>>> partner_read = partner.read(partner_search, ['name', 'website'])
>>> partner_read
[{'website': '', 'name': 'Test 123', 'id': 119}, {'website': 'b', 'name': 'test
1234', 'id': 121}, {'website': False, 'name': 'Test SO', 'id': 124}, {'website':
False, 'name': 'Test SO', 'id': 125}, {'website': 'www.yourcompany.com', 'name':
'Your Company', 'id': 1}]

Dari hasil pencarian, bisa kita lihat bahwa pencarian dengan kriteria pertama saja menghasilkan 5
partner: [119, 121, 124, 125, 1] . Dari hasil pencarian tersebut, hanya satu partner saja (id: 119) yang
memenuhi kriteria kedua, yaitu website=''.

165/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.8 Program: laporan


Pada program berikut, kita akan membuat satu laporan sederhana, dalam format PDF, untuk model
res.partner, sesuai hasil pencarian. Program mempergunakan pustaka oerpapi.
Source code (11_8.py)
# 11_8.py
# (c) Noprianto <nop@tedut.com> GPL
#
# Membuat laporan sederhana (PDF)
import base64
import oerpapi
host = 'localhost'
db_name = 'test1'
user = 'demo'
password = 'demo'
client = oerpapi.OErpClient(host)
client.connect()
version = client.version()
print 'Terhubung pada %s, versi %s' %(host, version.get('server_version'))
client.login(db_name, user, password)
print 'Login dengan UserID: %s' %(client.uid)
search_name = raw_input('Mencari nama partner yang mengandung teks berikut: ')
search_data = [('name', 'ilike', search_name)]
print search_data
partner = client.get_model('res.partner')
partner_search = partner.search(search_data)
print 'Ditemukan %s partner' %(len(partner_search))
if partner_search:
report = client.get_report('res.partner', partner_search)
report_result = report.get()
if report_result:
fout = '/tmp/report.pdf'
f = open(fout, 'wb')
f.write(base64.decodestring(report_result))
f.close()
print 'Laporan disimpan pada %s' %(fout)
else:
print 'Laporan gagal dihasilkan'
else:
print 'Laporan tidak dibuat'

Jalankanlah program dengan cara berikut:


166/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


$ python 11_8.py
Terhubung pada localhost, versi 7.0-20140724-231255
Login dengan UserID: 3
Mencari nama partner yang mengandung teks berikut: tes
[('name', 'ilike', 'tes')]
Ditemukan 4 partner
Laporan disimpan pada /tmp/report.pdf

File yang dihasilkan adalah file PDF yang valid:


$ file /tmp/report.pdf
/tmp/report.pdf: PDF document, version 1.4

Contoh pencarian dengan hasil tidak ditemukan:


$ python 11_8.py
Terhubung pada localhost, versi 7.0-20140724-231255
Login dengan UserID: 3
Mencari nama partner yang mengandung teks berikut: tidak_ditemukan
[('name', 'ilike', 'tidak_ditemukan')]
Ditemukan 0 partner
Laporan tidak dibuat

delay_1, delay_2 dan number_of_tries


Berikut adalah simulasi pembuatan report dengan semua delay_1, delay_2 dan number_of_tries di set
ke 0. Pada bagian pertama dalam contoh, report gagal dibuat.
Pada bagian kedua, kita mengatur ulang ketiga variabel tersebut untuk nilai wajar (untuk localhost dan
laporan sangat sederhana), dan report berhasil dibuat.
>>> import oerpapi
>>> client = oerpapi.OerpClient('localhost')
>>> client.connect()
>>>
>>> client.login('test1', 'demo', 'demo')
>>> client.uid
3
>>>
>>> partner = client.get_model('res.partner')
>>> search_data = [('name', 'ilike', 'tes')]
>>> partner_search = partner.search(search_data)
>>> partner_search
[119, 121, 124, 125]
>>>
>>> report = client.get_report('res.partner', partner_search)
>>> report.delay_1 = 0
>>> report.delay_2 = 0
>>> report.number_of_tries = 0
>>> report_result = report.get()
>>> report_result
''
>>>
>>> report.delay_1 = 1
>>> report.delay_2 = 0.5

167/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> report.number_of_tries = 50
>>> report_result = report.get()
>>> len(report_result)
25451

168/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.9 Program: buat, ganti nama, kopi, hapus database


Pada program berikut, kita akan membuat satu database, dengan opsi untuk menambahkan demo.
Database yang baru dibuat tersebut kemudian bisa di-ganti nama, dikopi dan dihapus. Program
mempergunakan pustaka oerpapi.
Source code (11_9.py)
#
#
#
#
#
#
#

11_9.py
(c) Noprianto <nop@tedut.com> GPL
Membuat database
Mengganti nama database
Mengopi database
Menghapus database

import oerpapi
host = raw_input('Server: ')
print 'Mencoba melakukan koneksi ke %s pada port default...' %(host)
client = oerpapi.OErpClient(host)
client.connect()
version = client.version()
print 'Versi: %s' %(version.get('server_version'))
db = client.get_db()
admin_password = raw_input('Masukkan password admin: ')
db_name = raw_input('Masukkan nama database yang ingin dibuat: ')
password = raw_input('Masukkan password yang ingin digunakan: ')
demo = False
if raw_input('Input Y apabila ingin menggunakan contoh data: ') == 'Y':
demo = True
db.admin_password = admin_password
print 'Mohon tunggu...'
db.create(db_name, demo, 'id_ID', password)
print db.list()
new_name = raw_input('Masukkan nama database yang baru (ENTER=lewatkan): ')
new_name = new_name.strip()
if new_name:
db.rename(db_name, new_name)
db_name = new_name
print db.list()
copy_name = raw_input('Mengopi database ke (ENTER=lewatkan): ')
copy_name = copy_name.strip()
if copy_name:
db.duplicate(db_name, copy_name)
print db.list()

169/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


if raw_input('Input Y untuk menghapus database %s: ' %(db_name)) == 'Y':
db.drop(db_name)
print db.list()

Jalankanlah program dengan cara berikut:


$ python 11_9.py
Server: localhost
Mencoba melakukan koneksi ke localhost pada port default...
Versi: 7.0-20140724-231255
Masukkan password admin: myadminpassword
Masukkan nama database yang ingin dibuat: test9
Masukkan password yang ingin digunakan: password_test9
Input Y apabila ingin menggunakan contoh data:
Mohon tunggu...
['test1',
'test1_copy',
'test2',
'test3',
'test30',
'test3_new',
'test9',
'test_baru', 'test_baru2']
Masukkan nama database yang baru (ENTER=lewatkan): test9_rename
['test1', 'test1_copy', 'test2', 'test3', 'test30', 'test3_new', 'test9_rename',
'test_baru', 'test_baru2']
Mengopi database ke (ENTER=lewatkan): test9_copy
['test1', 'test1_copy', 'test2', 'test3', 'test30', 'test3_new', 'test9_copy',
'test9_rename', 'test_baru', 'test_baru2']
Input Y untuk menghapus database test9_rename: Y
['test1', 'test1_copy', 'test2', 'test3', 'test30', 'test3_new', 'test9_copy',
'test_baru', 'test_baru2']

Dalam contoh tersebut:


Kita tidak menambahkan demo ke dalam database pada saat membuat database test9
Database tersebut kita ganti namanya menjadi test9_rename
Database tersebut kita kopikan ke test9_copy
Pada akhirnya, database test9_rename kita hapus
Perhatikanlah bahwa kita tidak bisa mengopikan ke database yang telah ada sebelumnya:
$ python 11_9.py
Server: localhost
Mencoba melakukan koneksi ke localhost pada port default...
Versi: 7.0-20140724-231255
Masukkan password admin: myadminpassword
Masukkan nama database yang ingin dibuat: test10
Masukkan password yang ingin digunakan: password_test10
Input Y apabila ingin menggunakan contoh data:
Mohon tunggu...
['test1', 'test10', 'test1_copy', 'test2', 'test3', 'test30', 'test3_new',
'test9_copy', 'test_baru', 'test_baru2']
Masukkan nama database yang baru (ENTER=lewatkan):
['test1', 'test10', 'test1_copy', 'test2', 'test3', 'test30', 'test3_new',
'test9_copy', 'test_baru', 'test_baru2']

170/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Mengopi database ke (ENTER=lewatkan): test9_copy
Traceback (most recent call last):
File "11_9.py", line 43, in <module>
db.duplicate(db_name, copy_name)

raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault database "test9_copy" already exists

Bahasa yang dipergunakan


Bahasa yang dipergunakan bisa didapatkan dengan memanggil fungsi list_lang. Perhatikanlah bahwa
tidak semua terjemahan adalah lengkap.
>>> import oerpapi
>>> client = oerpapi.OErpClient('localhost')
>>> client.connect()
>>>
>>> db = client.get_db()
>>> langs = db.list_lang()
>>> print len(langs)
81
>>>
>>> langs_id = [x[0] for x in langs]
>>> langs_id
['ab_RU', 'sq_AL', 'am_ET', 'ar_SY', 'bs_BS', 'bg_BG', 'ca_ES', 'zh_CN', 'zh_HK',
'zh_TW', 'hr_HR', 'cs_CZ', 'da_DK', 'nl_NL', 'en_CA', 'en_GB', 'en_US', 'et_EE',
'fi_FI', 'nl_BE', 'fr_BE', 'fr_CH', 'fr_FR', 'gl_ES', 'de_DE', 'el_GR', 'gu_IN',
'he_IL', 'hi_IN', 'hu_HU', 'id_ID', 'iu_CA', 'it_IT', 'ja_JP', 'tlh_TLH', 'ko_KP',
'ko_KR', 'lo_LA', 'lv_LV', 'lt_LT', 'ml_IN', 'mn_MN', 'nb_NO', 'oc_FR', 'fa_IR',
'pl_PL', 'pt_BR', 'pt_PT', 'ro_RO', 'ru_RU', 'sr_RS', 'sr@latin', 'si_LK', 'sk_SK',
'sl_SI', 'es_AR', 'es_BO', 'es_CL', 'es_CO', 'es_CR', 'es_DO', 'es_EC', 'es_GT',
'es_HN', 'es_MX', 'es_NI', 'es_PA', 'es_PE', 'es_PR', 'es_PY', 'es_SV', 'es_UY',
'es_VE', 'es_ES', 'sv_SE', 'te_IN', 'th_TH', 'tr_TR', 'uk_UA', 'ur_PK', 'vi_VN']
>>>

171/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.10 Program: dump dan restore database


Pada program berikut, kita akan melakukan dump/backup sebuah database dan kemudian melakukan
restore dari file backup sebelumnya ke database baru. Program mempergunakan pustaka oerpapi.
Source code (11_10.py)
#
#
#
#
#

11_10.py
(c) Noprianto <nop@tedut.com> GPL
Dump/backup database
Restore database

import base64
import oerpapi
host = raw_input('Server: ')
print 'Mencoba melakukan koneksi ke %s pada port default...' %(host)
client = oerpapi.OErpClient(host)
client.connect()
version = client.version()
print 'Versi: %s' %(version.get('server_version'))
db = client.get_db()
db_list = db.list()
print 'Database yang tersedia: %s' %(db_list)
db_name = raw_input('Database yang ingin dibackup: ')
admin_password = raw_input('Masukkan password admin: ')
db.admin_password = admin_password
fout = '/tmp/backup.sql'
print 'Mohon tunggu...'
backup = db.dump(db_name)
if backup:
f = open('/tmp/backup.sql', 'wb')
f.write(base64.decodestring(backup))
f.close()
print 'Backup disimpan pada %s' %(fout)
else:
print 'Backup gagal didapatkan'
db_name = raw_input('Ingin restore %s ke database: ' %(fout))
db.restore(db_name, backup)

Jalankanlah program dengan cara berikut:

172/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


$ python 11_10.py
Server: localhost
Mencoba melakukan koneksi ke localhost pada port default...
Versi: 7.0-20140724-231255
Database yang tersedia: ['test1', 'test10', 'test1_copy', 'test2', 'test3',
'test30', 'test3_new', 'test9_copy', 'test_baru', 'test_baru2']
Database yang ingin dibackup: test10
Masukkan password admin: myadminpassword
Mohon tunggu...
Backup disimpan pada /tmp/backup.sql
Ingin restore /tmp/backup.sql ke database: test10_restore

Format file dump


$ file /tmp/backup.sql
/tmp/backup.sql: PostgreSQL custom database dump v1.12-0

173/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

9.11 Menggunakan xmlrpclib


Sebagaimana dibahas sebelumnya, pada dasarnya, kita cukup menggunakan xmlrpclib untuk berbicara
dengan server OpenERP. Contoh-contoh sebelumnya yang menggunakan pustaka oerpapi hanyalah
bertujuan agar lebih mudah dan nyaman.
Tips: Untuk informasi selengkapnya tentang web service/API, bacalah juga dokumentasi API
OpenERP. Apabila diperlukan, Anda juga bisa membaca source code pustaka oerpapi ataupun Bab 5
tentang Model pada OpenERP.
Pertama-tama, kita perlu import module xmlrpclib:
>>> import xmlrpclib

/xmlrpc/common
Setelah kita mengetahui host dan port, pertama-tama, umumnya kita ingin melakukan koneksi ke
service /xmlrpc/common:
>>> host = 'localhost'
>>> port = 8069
>>> protocol = 'http://'
>>> url = '%s%s:%s/xmlrpc/common' %(protocol, host, port)
>>> url
'http://localhost:8069/xmlrpc/common'
>>> sock_common = xmlrpclib.ServerProxy(url)
>>> sock_common
<ServerProxy for localhost:8069/xmlrpc/common>
>>>

Service ini menyediakan berbagai utiliti seperti login. Ketika login sukses dilakukan, kita mendapatkan
uid.
>>>
>>>
>>>
>>>
>>>
3
>>>

db_name = 'test1'
user = 'demo'
password = 'demo'
uid = sock_common.login(db_name, user, password)
uid

/xmlrpc/object
Kita umumnya menggunakan service /xmlrpc/object dan fungsi execute:
>>> url_object = '%s%s:%s/xmlrpc/object' %(protocol, host, port)
>>> url_object
'http://localhost:8069/xmlrpc/object'
>>> sock_object = xmlrpclib.ServerProxy(url_object)

174/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> sock_object
<ServerProxy for localhost:8069/xmlrpc/object>
>>>

Dengan informasi database, uid dan password, kita bisa bekerja dengan object-object OpenERP.
Sebagai contoh, kita akan membuat sebuah partner baru:
>>> partner_data = {'name': 'test xmlrpclib'}
>>> partner_id = sock_object.execute(db_name, uid, password, 'res.partner',
'create', partner_data)
>>> partner_id
126
>>>

Fungsi execute juga bisa dipergunakan untuk mengupdate, membaca, mencari dan menghapus seperti
contoh-contoh berikut:
>>> partner_update = {'name': 'test xmlrpclib updated'}
>>> sock_object.execute(db_name, uid, password, 'res.partner', 'write',
[partner_id], partner_update)
True
>>>
>>> fields = ['name']
>>> partner_read = sock_object.execute(db_name, uid, password, 'res.partner',
'read', [partner_id], fields)
>>> partner_read
[{'name': 'test xmlrpclib updated', 'id': 126}]
>>>
>>> search_data = [('name', 'ilike', 'tes')]
>>> partner_search = sock_object.execute(db_name, uid, password, 'res.partner',
'search', search_data)
>>> partner_search
[119, 121, 124, 125, 126]
>>>
>>> sock_object.execute(db_name, uid, password, 'res.partner', 'unlink',
[partner_id])
True
>>>

/xmlrpc/db
Menggunakan service /xmlrpc/db, kita bisa bekerja dengan database:
>>> url_db = '%s%s:%s/xmlrpc/db' %(protocol, host, port)
>>> url_db
'http://localhost:8069/xmlrpc/db'
>>> sock_db = xmlrpclib.ServerProxy(url_db)
>>> sock_db
<ServerProxy for localhost:8069/xmlrpc/db>

175/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>>

Sebagai contoh, kita memanggil fungsi list untuk mendapatkan daftar database:
>>> sock_db.list()
['test1', 'test10', 'test10_restore', 'test1_copy', 'test2', 'test3', 'test30',
'test3_new', 'test9_copy', 'test_baru', 'test_baru2']
>>>

Fungsi create_database dapat digunakan untuk membuat database baru. Perhatikanlah bahwa kita perlu
melewatkan password admin sebagai argumen pertama ketika memanggil fungsi yang membutuhkan
hak admin.
>>> sock_db.create_database('test40', False, 'id_ID', 'password_test40')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>

raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault AccessDenied: 'Access denied.'>
>>>

Pemanggilan fungsi create_database tersebut gagal karena password admin tidak dilewatkan. Kita
melakukan koreksi dengan cara berikut:
>>> sock_db.create_database('myadminpassword', 'test40', False, 'id_ID',
'password_test40')
True
>>>
>>> sock_db.list()
['test1', 'test10', 'test10_restore', 'test1_copy', 'test2', 'test20', 'test3',
'test30', 'test3_new', 'test40', 'test9_copy', 'test_baru', 'test_baru2']
>>>

Fungsi drop dapat digunakan untuk menghapus database. Sebagai contoh:


>>> sock_db.drop('admin20142', 'test40')
True
>>>

/xmlrpc/report
Menggunakan service /xmlrpc/report, kita bisa bekerja dengan report. Untuk informasi selengkapnya,
bacalah dokumentasi API OpenERP.

176/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10. Lampiran: Python Dasar


Penulis: Noprianto

Tentang dokumen ini

Dokumen ini membahas dasar-dasar bahasa pemrograman Python, untuk versi 2.x.

Dokumen ini merupakan revisi ke 6, dimana pada awalnya, ditulis untuk Python versi 2.5, namun
telah sedikit disesuaikan untuk Python 2.7.

Python Dasar (c) 2009-2012,2014 Noprianto (tedut.com)

Revisi terbaru (dalam format ODT/PDF) selalu


https://github.com/nopri/id-python atau http://tedut.com.

Dokumen ini diharapkan dapat berguna namun tidak menggaransi apapun.

177/232

bisa

didapatkan

secara

bebas

dari

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.1 Penulisan source code


a) Indentasi adalah 4 karakter.
b) Untuk indentasi, gunakan hanya spasi, jangan gunakan TAB.
c) Panjang baris maksimal adalah 79 karakter. Pindah baris langsung dalam kurung dan hanya
gunakan backslash (\) apabila diperlukan.
d) Panjang baris maksimal untuk docstring dan komentar adalah 72 karakter.
e) Gunakan pemisah dua baris kosong antara class / fungsi top-level.
f) Gunakan pemisah satu baris kosong antara method dalam class.
g) Import setiap modul dilakukan per baris, dengan urutan kelompok: standard library, pustaka pihak
ketiga, pustaka lokal. Pisahkanlah masing-masing kelompok import dengan sebuah baris kosong.
h) Struktur program Python:
1. Shebang Line
2. Komentar dan docstring
3. Import
4. Global dan konstanta
5. Class dan fungsi
i) Aturan nama:
1. Paket: lowercase
2. Modul: lowercase, underscore bisa digunakan kalau diperlukan.
3. Class: kapitalisasi per kata (huruf pertama setiap kata menggunakan kapital)
4. Exception: kapitalisasi per kata (huruf pertama setiap kata menggunakan kapital). Gunakan
tambahan Error untuk menandakan kesalahan.
5. Fungsi dan method class: lowercase, setiap kata dipisahkan underscore.
6. Variabel: lowercase, setiap kata dipisahkan underscore.
7. Konstanta: UPPERCASE, setiap kata dipisahkan underscore.
j) Case sensitive!

178/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Untuk informasi lebih lanjut, bacalah juga PEP 8 (Style Guide for Python Code,
http://legacy.python.org/dev/peps/pep-0008/).

179/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.2 Sekilas tentang Python


a) Open Source
1. Sesuai dengan sertifikasi Open Source Initiative.
2. Kompatibel dengan GPL (versi 2.0.1 dan yang lebih baru), menurut Free Software Foundation.
Walau demikian, tidak ada pembatasan copyleft GPL.
3. Bebas digunakan, termasuk untuk produk proprietary.
4. Selengkapnya, https://www.python.org/psf/.
b) Sintaks sederhana, jelas, fleksibel, mudah dipelajari.
c) Mendukung multi-paradigma, salah satunya Object-oriented.
d) Tipe data very high level.
e) Standard library yang lengkap.
f) Berjalan di banyak sistem.
g) Dapat diextend dengan C/C++
h) Type system: Strong, Dynamic, Duck

Untuk informasi lebih lanjut, kunjungilah situs web Python https://www.python.org/

180/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.3 Interpreter Python (interaktif)


a) Path default executable python:
1. Windows: c:\pythonXY\python.exe. XY adalah versi Python. Contoh: c:\python25\python.exe
2. Linux: /usr/bin/python atau /usr/bin/pythonX.Y (umumnya menggunakan symlink
/usr/bin/python). XY adalah versi Python.
b) Untuk menjalankan interpreter Python:
1. Windows: Masuk ke command prompt, masuk ke direktori instalasi Python, jalankan
python.exe. Dapat pula mengakses dari Start Menu. Daftarkanlah direktori instalasi Python ke
PATH apabila diperlukan.
2. Linux: Masuk ke terminal, berikan perintah: 'python' (tanpa tanda kutip).
c) Keluar dari sesi interaktif interpreter Python:
1. Windows: Ctrl-Z, ENTER.
2. Linux: Ctrl-D
d) Untuk mencetak ke standard output, gunakan print.
e) Untuk membaca string dari standard input, raw_input() bisa digunakan.
f) Beberapa fungsi lain:
1. abs()
2. chr()
3. dir()
4. max()
5. min()
6. pow()

181/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.4 Script Python


a) Simpan dengan ekstensi nama file py. Contoh: hello.py.
b) Shebang
1. #, !, diikuti Path ke executable Python
2. Contoh di Linux: #!/usr/bin/python
3. Contoh di Windows: #!c:\python25\python.exe
4. Di Linux, bisa gunakan bantuan env, sehingga shebang line menjadi #!/usr/bin/env python
a) Sesuaikan path ke env
c) Jalankan di command line: python <script.py>
d) Di Linux, berikan hak akses executable dengan perintah:
1. chmod +x <script.py>
2. Selanjutnya, bisa dijalankan langsung dengan ./script.py atau script.py (apabila direktori aktif
terdaftar di $PATH) dari prompt.

182/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.5 Tipe builtin, collection dan operator


Tipe

Detil

None

None Object

Number

Boolean (bool)

Set

Batas int bisa dilihat pada sys.maxint

Long integer (long)

Gunakan suffix L atau l

Batas long sesuai memori

Floating point (float)

pecahan

bisa ditulis dalam e atau E

Complex (complex)

bilangan kompleks

memiliki atribut real (real) dan imag (imajiner).

imajiner bisa dituliskan dengan suffix j atau J.

dir: conjugate, imag, real

Set (set): mutable

True atau False

Integer (int)

Catatan

dir: add, clear, copy, difference, difference_update,


discard, intersection, intersection_update, issubset,
issuperset, pop, remove, symmetric_difference,
symmetric_difference_update, union, update

Frozen Set (frozenset): immutable

dir: copy, difference, intersection, issubset,

183/232

Unordered

Semua item
dalam set
harus
immutable

Dapat dibuat
dari item

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Tipe

Detil

Catatan

issuperset, symmetric_difference, union

Sequence

String (str)

immutable

dapat dibentuk dengan pasangan:

kutip tunggal (')

kutip ganda ('')

triple kutip tunggal (' ' ')

triple kutip ganda ('' '' '')

Pasangan triple-kutip bisa mengembed newline.

Berlaku penggunaan escape character.

Dapat dituliskan dalam bentuk raw string (diawali r


atau R). Contoh: r'c:\window'

Raw string, apabila diakhiri dengan backslash (\),


harus berjumlah genap.

dir: capitalize, center, count, decode, encode,


endswith, expandtabs, find, index, isalnum, isalpha,
isdigit, islower, isspace, istitle, isupper, join, ljust,
lower, lstrip, partition, replace, rfind, rindex, rjust,
rpartition, rsplit, rstrip, split, splitlines, startswith,
strip, swapcase, title, translate, upper, zfill.

Unicode String (unicode)

immutable

184/232

iterable

Unik

Dapat
dioperasikan
sebagai
himpunan

Memiliki
sifat iterable

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Tipe

Detil

Diawali dengan u atau U, diikuti 4 digit hexa kode


karakter unicode.

Berlaku penggunaan escape character.

Bisa diisi dengan \N{Name}, dimana Name sesuai


aturan unicode. Contoh: \N{Copyright Sign}.

Apabila menggunakan raw string, ditulis dengan ur.

dir: method pada str, ditambah isdecimal dan


isnumeric.

Tuple (tuple)

immutable

Akses lebih cepat

Dapat dibuat dengan tuple(), atau dengan


menempatkan anggota dalam kurung ( dan ).

Koma tambahan bisa dituliskan setelah anggota


terakhir. Contoh: (1,2,3,)

Tuple dengan satu anggota harus dituliskan dengan


menambahkan koma. Contoh: (1,) dan bukan (1)

dir: index, count (versi 2.6 ke atas)

List (list)

mutable

Lihat range()

Dapat dibuat dengan list(), atau dengan menempatkan


anggota dalam kurung [ dan ].

Koma tambahan bisa dituliskan setelah anggota


terakhir. Contoh: [1,2,3,]

dir: append, count, extend, index, insert, pop, remove,

185/232

Catatan

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Tipe

Detil

Catatan

reverse, sort.

Mapping

File

Xrange (xrange)

immutable

Dibuat dengan xrange()

Untuk perulangan, relatif lebih cepat dari penggunaan


range().

Dictionary (dict)

Key harus berupa tipe immutable

Value dapat berupa hampir semua object Python

Dapat dibuat dengan dict(), atau dengan menempatkan


key:value dalam kurung { dan }.

dir: clear, copy, fromkeys, get, has_key, items,


iteritems, iterkeys, itervalues, keys, pop, popitem,
setdefault, update, values

Unordered
(lihatlah juga
pembahasan
Collection)

File (file)

Dibuka dengan open(name[, mode[, buffering]]) atau


file(name[, mode[, buffering]])

Mode file: r(read, default), w(write), a(append)

Ditutup dengan method close() objek file

dir: close, closed, encoding, fileno, flush, isatty,


mode, name, newlines, next, read, readinto,
readline, readlines, seek, softspace, tell, truncate,
write, writelines, xreadlines

Collection
Sebagai alternatif dari container built-in seperti dict, list, set dan tuple, terdapat pula berbagai
186/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


collection, yang diimplementasikan dalam module collections (versi 2.4).

namedtuple, versi 2.6

deque, versi 2.4

Counter, versi 2.7

OrderedDict, versi 2.7

defaultdict, versi 2.5

Operator
Perbandingan boolean
<, lebih kecil
<=, lebih kecil sama dengan
>, lebih besar
>=, lebih besar sama dengan
==, sama dengan
!=, tidak sama dengan
Operator Logical
not, logical negasi
and, logical and
or, logical or
Operator aritmatika
*, perkalian
/, pembagian
//, pembagian integer
%, sisa bagi
+, penjumlahan
187/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


-, pengurangan
Operator bit
~, bitwise complement
<<, shift left
>>, shift right
&, bitwise and
|, bitwise or
^, bitwise xor
Operator pada sequence
in: terdapat di dalam. Gunakan not in untuk kebalikannya.
Operator tambahan string:
%: pemformatan

Index dan Slice:


Beberapa sequence seperti string, unicode string, list dan tuple mendukung index dan slicing, dengan
sintaks:
s[i]: item ke i dari sequence s, dimulai dari 0
s[i:j]: item ke i sampai j dari sequence s
s[i:j:k]: item ke i sampai j dari sequence s, dengan step k

Catatan untuk i,j dan k:


Apabila nilai i dan j negatif, maka index relatif dari akhir sequence.
Jika i tidak diberikan, maka default ke 0
Jika j tidak diberikan, maka default ke len(s)
Jika k tidak diberikan, maka default ke 1. Nilai k tidak bisa diisi dengan 0.

188/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Jika i lebih besar atau sama dengan j, maka menghasilkan slice kosong.

Untuk tipe xrange, index didukung namun slicing tidak didukung.

Lain-lain:
Beberapa fungsi:
type(object): mengembalikan tipe object
id(object): mengembalikan alamat memori object
ininstance(object, class-or-type-or-tuple): mengembalikan apakah object merupakan instance
dari class.
Kategori tipe juga mencakup Callable (dapat dipanggil), Modules (setelah diimport), Classes dan
Type.

189/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.6 Kondisi
Sintaks if
if <expression>:
<statement>
<statement>
..
[elif <expression>:
<statement>
<statement>
..
]
[else:
<statement>
<statement>
..
]

Contoh if:
>>> a=10
>>> if a > 5:
...

print 'a besar dari 5'

...
a besar dari 5

Catatan:

190/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


pass dapat digunakan untuk blok kosong.
Python tidak mendukung switch/case

191/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.7 Perulangan
Sintaks for
for <target_list> in <expression_list>:
<statement>
<statement>
...
[else:
<statement>
<statement>
..
]

Contoh for:
>>> for i in range(1,10,2):
...

print i

...
1
3
5
7
9

Sintaks while
while <expression>:
<statement>

192/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


<statement>
...
[else:
<statement>
<statement>
..
]

Contoh while:
>>> a=1
>>> while a<5:
...

print a

...

a += 1

...
1
2
3
4

Catatan
pass dapat digunakan untuk blok kosong.
Statement break digunakan untuk keluar dari perulangan.
Statement continue digunakan untuk melanjutkan ke iterasi berikutnya.
Statement pada blok else akan dikerjakan apabila perulangan selesai, namun tidak oleh statement
break.

193/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.8 Fungsi
Deklarasi fungsi
def <func_name>([parameter_list]):
<statement>
<statement>
...
[return <return_value>]

Catatan:
ketika return tidak didefinisikan, None akan dikembalikan

Documentation String (docstring)


Setiap fungsi dapat memiliki docstring (documentation string), yang umumnya mendeskripsikan
bagaimana cara menggunakan fungsi tersebut. Docstring dapat dituliskan sebagai string langsung
setelah deklarasi fungsi. Contoh:

def test():
...

'docstring fungsi test'

...

print 'test'

...

Untuk mengetahui docstring fungsi test, akseslah atribut __doc__ dari fungsi test. Contoh:

>>> test.__doc__
194/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


'docstring fungsi test'

Docstring yang didefinisikan juga berguna dalam penggunaan bersama fungsi help() di sesi interactive:

>>> help(test)
Help on function test in module __main__:

test()
docstring fungsi test

Pemanggilan fungsi
Pemanggilan fungsi harus melihatkan penggunaan (), sesuai argumen fungsi. Tanpa (), python tidak
akan menganggap sintaks tersebut sebagai sintaks yang salah, tetapi tidak akan dikerjakan.

Contoh yang salah:


>>> test
<function test at 0xb7c305dc>

Contoh yang benar:


>>> test()
test

Variabel global
Setiap fungsi akan memiliki variabel lokal sendiri. Namun, ada kalanya, akses ke variabel global
diperlukan.

195/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Untuk mengassign nilai tertentu ke variabel global, gunakan keyword global.

Contoh berikut dimaksudkan untuk mengubah variabel global x menjadi 20, namun tidak bekerja:

>>> x=10
>>> def testx():
...

x=20

...

print x

...
>>> x
10
>>> testx()
20
>>> x
10
>>>

Contoh yang benar adalah:


>>> x=10
>>> def testx():
...

global x

...

x=20

...

print x

...
>>> x
10

196/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> testx()
20
>>> x
20
>>>

Walau demikian, untuk sekedar mereferensi ke variabel global, keyword global tidak diperlukan.

Argumen fungsi
Argumen fungsi bisa diberikan, tanpa harus menyebutkan tipe data. Apabila lebih dari 1 argumen,
maka deretkanlah dengan dipisahkan oleh koma. Pemanggilan fungsi selanjutnya harus disesuaikan
dengan argumen yang didefinisikan, kecuali default argument digunakan (lihat pembahasan
berikutnya).

Contoh 1:
>>> def kuadrat(x):
...

return x*x

...
>>> hasil=kuadrat(12)
>>> print hasil
144

Contoh 2:
>>> def kali(a,b):
...

return a*b

...
>>> hasil=kali(2,4)
197/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> print hasil
8

Argumen juga bisa dipanggil dengan menyebutkan nama (keyword) pada parameter formal, sehingga
dapat dipanggil dengan urutan yang tidak sesuai dengan saat deklarasi. Contoh:

>>> def kali2(a,b):


...

print '(%d x %d) = %d' %(a, b, a*b)

...
>>> kali2(b=20, a=10)
(10 x 20) = 200
>>>

Ketika menggunakan keyword argument, pastikan kesalahan-kesalahan seperti berikut tidak dilakukan:
non-keyword argument diberikan keyword argument
duplikasi argumen
salah memberikan keyword

Argumen default
Argumen default memungkinkan pengguna fungsi untuk memanggil fungsi dengan argumen yang lebih
sedikit/sederhana dalam kondisi normal, namun memiliki keleluasaan untuk memanggil fungsi dengan
semua argumen diberikan.

Argumen default digunakan apabila sebuah argumen memiliki nilai tertentu yang umum (digunakan
oleh pemanggil fungsi), namun tetap dimungkinkan untuk diberikan nilai lain.

Argumen default sangat umum digunakan di Python.

198/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Sebagai contoh, kita mendefinisikan sebuah fungsi cetak_nama, dengan dua argumen:
name: nama yang akan dicetak
prefix: prefix pencetakan

Dalam kondisi normal, fungsi akan selalu mencetak tulisan 'Nama Anda adalah ' (prefix) diikuti oleh
name yang diberikan. Apabila prefix ingin diganti, pengguna fungsi tetap dapat melakukannya.

>>> def cetak_nama(name, prefix='Nama Anda adalah '):


...

print prefix + name

...
>>> cetak_nama('piton')
Nama Anda adalah piton
>>> cetak_nama('piton','Nama=')
Nama=piton

Argumen *arg (tuple)


Ketika parameter formal dituliskan dalam bentuk *arg, maka fungsi akan menerima argumen berupa
tuple. Contoh:

>>> def testt(*t):


...

for i in t:

...

print i

...
>>> testt(1,2,3,4,5)
1

199/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


2
3
4
5
>>> testt('halo','apa','kabar')
halo
apa
kabar

Dengan cara seperti ini, jumlah argumen tidak didefinisikan secara kaku.

Argumen **arg (dictionary)


Ketika parameter formal dituliskan dalam bentuk **arg, maka fungsi akan menerima argumen berupa
dictionary. Contoh:

>>> def testd(**arg):


...

keys = arg.keys()

...

for k in keys:

...

print '%s=>%s' %(k, arg[k])

...

>>> testd(nama='piton', umur=28, kabar='Baik')


nama=>piton
kabar=>Baik
umur=>28

200/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>>

Dengan cara seperti ini, argumen tidak didefinisikan secara kaku. Catatan mulai versi 2.6: pada saat
pemanggilan fungsi dengan sintaks **, mapping lain bisa dipergunakan (tidak harus dictionary).

201/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.9 Class
Berikut adalah sintaks class:

class <class_name> ([baseclasses]):


<statement>
<statement>
...

Catatan:
Dideklarasikan dengan keyword class
Class mendukung docstring seperti halnya fungsi
Setiap definisi method class akan menggunakan keyword self sebagai argumen pertama method,
yang dapat digunakan untuk merujuk ke diri sendiri (object).
Untuk merujuk ke anggota dalam class, gunakanlah kata kunci self.
Constructor class adalah method dengan nama __init__.
Python mendukung multiple inheritance
Python menggunakan name mangling untuk identifier yang diawali oleh paling tidak dua
underscore dan diakhiri paling banyak satu underscore. Name mangling tersebut dapat digunakan
sebagai 'private variable'.
Mengenal dua tipe class: old-style (classic) dan new-style (diperkenalkan sejak Python versi 2.2).
Default adalah old-style pada python 2.x. Untuk membuat class new-style, gunakan base class
berupa class new-style atau object (apabila base class tidak diperlukan).
Instansiasi menggunakan notasi fungsi. Argumen dilewatkan pada method __init__.
Terdapat berbagai nama method spesial, yang diantaranya dapat dilakukan untuk kustomisasi,
emulasi, koersi, context manager with (versi 2.5 ke atas), dan lainnya. Ini merupakan pendekatan
yang dilakukan oleh Python untuk operator overloading.

202/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Contoh 1, class kosong:


>>> class MyClass1:
...

pass

...
>>> c1 = MyClass1()
>>> type(c1)
<type 'instance'>
>>> c1
<__main__.MyClass1 instance at 0xb7bf1fcc>

Contoh 2, class dengan docstring dan constructor:


>>> class MyClass2:
...

'keterangan MyClass2'

...

def __init__(self, x):

...

print 'Inisialisasi...'

...

print x

...
>>> c2 = MyClass2(10)
Inisialisasi...
10
>>> c2.__doc__
'keterangan MyClass2'
>>>

203/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Contoh 3, atribut class:
>>> class MyClass3:
...
...
...
...

def __init__(self, x):


self.x = x
def method1(self):
print '-' * self.x

...

def method2(self):

...

self.method1()

...
>>> c3 = MyClass3(5)
>>> c3.x
5
>>> c3.method1()
---->>> c3.x = 10
>>> c3.method1()
--------->>> c3.method2()
--------->>>

Contoh 4, inheritance sederhana:


>>> class Base:
...

def method1(self):

...

print 'base....'

204/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


...
>>> class Derived1(Base):
...

def method2(self):

...

print 'derived1...'

...
>>> class Derived2(Base):
...

def method1(self):

...
...

print 'method1 of derived2...'


def method2(self):

...

print 'derived2...'

...
>>> c4 = Derived1()
>>> c4.method1()
base....
>>> c4.method2()
derived1...
>>>
>>> c5 = Derived2()
>>> c5.method1()
method1 of derived2...
>>> c5.method2()
derived2...
>>>

Catatan: pada class new-style, super() bisa digunakan untuk merefer ke class parent. Lihatlah juga
contoh 8.

205/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Contoh 5, name mangling sederhana:


>>> class Mangling:
...
...

def __init__(self, x):


self.__x = x

...

def method1(self):

...

print self.__x

...
>>> c6 = Mangling(10)
>>> c6.__x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Mangling instance has no attribute '__x'
>>> c6.method1()
10
>>> c6.__x=20
>>> c6.method1()
10
>>>

Contoh 6, class sebagai struct/record:


>>> class Struct1:
...

pass

...
>>> c7 = Struct1()
>>> c7.name = 'test'

206/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> c7.address = 'test address'
>>>
>>> print c7.name
test
>>> print c7.address
test address

Contoh 7, akses constructor parent pada class old-style


>>> class Base:
...
...

def __init__(self):
print 'Inisialisasi (Base)...'

...
>>>
>>> class Derived1(Base):
...
...

def __init__(self):
print 'Inisialisasi (Derived1)...'

...
>>> class Derived2(Base):
...

def __init__(self):

...

Base.__init__(self)

...

print 'Inisialisasi (Derived2)...'

...
>>> d1 = Derived1()
Inisialisasi (Derived1)...
>>> d2 = Derived2()
Inisialisasi (Base)...

207/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Inisialisasi (Derived2)...

Pada class Derived2, pemanggilan constructor parent dilakukan.

Contoh 8, akses constructor parent pada class new-style


>>> class Base(object):
...
...

def __init__(self):
print 'Inisialisasi (Base)...'

...
>>> class Derived1(Base):
...
...

def __init__(self):
print 'Inisialisasi (Derived1)...'

...
>>> class Derived2(Base):
...

def __init__(self):

...

super(Derived2, self).__init__()

...

print 'Inisialisasi (Derived2)...'

...
>>> d1 = Derived1()
Inisialisasi (Derived1)...
>>> d2 = Derived2()
Inisialisasi (Base)...
Inisialisasi (Derived2)...

Pada class Derived2, pemanggilan constructor parent dilakukan.

208/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Contoh 9, operator overloading
>>> class Overload1:
...
...

def __init__(self, x):


self.x = x

...

def __add__(self, y):

...

return self.x + y

...
>>> o1 = Overload1(10)
>>> o1 + 5
15
>>>

>>> class Overload2:


...
...

def __init__(self, x):


self.x = x

...

def __sub__(self, y):

...

return self.x - y

...

def __mul__(self, y):

...

return self.x * y

...
>>> o2 = Overload2(10)
>>> o2 - 5
5
>>> o2 * 10
100
>>>

209/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

>>> class MyStr:


...
...
...
...
...
...

def __init__(self, x):


self.x = str(x)
def __mul__(self, y):
return str(self.x) * y
def __sub__(self, s):
return str(self.x).replace(s, '')

...
>>>
>>> a = 'halo apa kabar'
>>> a * 2
'halo apa kabarhalo apa kabar'
>>> a - 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'str' and 'str'
>>>
>>>
>>> s = MyStr('halo apa kabar')
>>> s * 2
'halo apa kabarhalo apa kabar'
>>> s - 'a'
'hlo p kbr'
>>>

210/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Contoh terakhir mendemonstrasikan class MyStr, dimana kita ingin mirip dengan str, namun
mengoverload operator -.

211/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.10 Modul-modul
Python datang dengan sangat baik modul siap pakai. Pengguna juga dapat menginstall modul tambahan
dari pihak ketiga, ataupun menggunakan modul yang dibuat sendiri. Modul-modul bisa pula
dikelompokkan menjadi package.

Modul dapat digunakan setelah diimport. Contoh penggunaan modul os untuk mendapatkan nama os:

>>> import os
>>> os.name
'posix'

Nama yang lebih pendek bisa digunakan, dengan import <module> as <alias>, sebagai contoh:
>>> import platform as p
>>> p.uname()
('Linux', 'nop1', '2.6.21.5-smp', '#2 SMP Tue Jun 19 14:58:11 CDT 2007', 'i686', 'Intel(R) Celeron(R)
CPU 2.50GHz')
>>>

Statement import selengkapnya:


import <module> [as <name>] (, <module> [as <name>] )
from <relative_module> import <identifier> [as <name>] (, <identifier> [as <name>] )
from <relative_module> import (<identifier> [as <name>] (, <identifier> [as <name>] )... [,])
from <module> import *

212/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Contoh modul
Beberapa contoh modul:
time : bekerja dengan waktu, contoh:
Epoch = waktu dimulai (1 Januari 1970, pukul 00:00)
Dapatkan detik sejak epoch:
time.time()
1228025944.210458
Informasi detil waktu sejak epoch (GMT):
time.gmtime(-100000000)
(1966, 10, 31, 14, 13, 20, 0, 304, 0)
time.gmtime(0)
(1970, 1, 1, 0, 0, 0, 3, 1, 0)
time.gmtime()
(2008, 11, 30, 6, 19, 48, 6, 335, 0)
Informasi detil waktu sejak epoch (lokal):
time.localtime()
(2008, 11, 30, 15, 43, 36, 6, 335, 0)
Parse time dari string (format bisa baca referensi modul time)
time.strptime('2008-11-12', '%Y-%m-%d')
(2008, 11, 12, 0, 0, 0, 2, 317, -1)
Mengembalikan string time dari detik sejak epoch (lokal):
time.ctime(1000)
'Thu Jan 1 07:16:40 1970'
Mengembalikan string time dari sequence time (lokal):
time.asctime((2008,10,11,23,11,22,0,0,0))
213/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


'Mon Oct 11 23:11:22 2008'
Mengembalikan detik sejak epoch dari sequence time (lokal):
time.mktime((2008,10,11,23,11,22,0,0,0))
1223741482.0
Memformat waktu dari sequence time (GMT atau lokal, bacalah referensi modul time):
time.strftime('%d-%m-%Y', time.localtime(1000000000))
'09-09-2001'
Dapatkan nama timezone (gunakan index 0, apabila non-DST):
time.tzname
('WIT', 'WIT')
Dapatkan selisih detik dari GMT:
time.timezone
-25200
Menunda eksekusi selama beberapa waktu tertentu (dalam detik):
time.sleep(1)
time.sleep(0.5)
random : bekerja dengan bilangan acak, contoh:
Mendapatkan bilangan acak antara 0.0 dan 1.0:
random.random()
0.47981142386967368
Mendapatkan bilangan acak antara dua integer (termasuk):
random.randint(1000,9999)
9923
Memilih bilangan acak dari range():
random.randrange(1, 100, 2)
214/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


51
Memilih bilangan acak dari sequence:
random.choice([1,2,3,4])
2
Mengacak sequence:
x=[1,2,3,4,5,6]
random.shuffle(x)
x
[1, 4, 2, 5, 3, 6]
sys: akses ke objek yang digunakan atau berhubungan dengan interpreter
contoh: argv, maxint, version, platform, prefix, executable
os : rutin sistem operasi
contoh: path, name
platform : identitas platform
contoh: uname, system
datetime : bekerja dengan tipe datetime
calendar : fungsi pencetakan kalender
math: fungsi-fungsi matematika
base64: encoding Base16, Base32, Base64
hashlib: (versi 2.5 ke atas) secure hash dan message digest seperti
SHA1/SHA224/SHA256/SHA384/SHA512 dan MD5
binascii: konversi binary-ascii
csv: baca tulis file csv
glob: pathname pattern expansion
linecache: akses ke baris tertentu dalam file

215/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


shutil: operasi file
tarfile: bekerja dengan file tar, tar.gz dan tar.bz2

Selengkapnya, lihatlah index modul pada dokumentasi Python.

Search path
Ketika suatu modul diimport, Python akan mencari ke:
direktori aktif
daftar direktori pada variabel PYTHONPATH
default path, lokasi instalasi python

Mulai versi 2.6, per-user site-packages didukung. Untuk informasi selengkapnya, bacalah juga
environment variable PYTHONUSERBASE dan PYTHONNOUSERSITE.

Compiled module
Ketika suatu modul berhasil diimport, versi byte-compiled modul (file bernama sama dengan modul,
namun dengan ekstensi .pyc/.pyo) akan coba dibuat. File byte-compiled tersebut dapat diload lebih
cepat.

Mulai versi 2.6, pembuatan .pyc/.pyo bisa dicegah dengan switch -B, atau environment variabel
PYTHONDONTWRITEBYTECODE.

Nama module
Setiap modul python memiliki nama masing-masing, yang dapat diakses dari properti __name__.
Contoh:
>>> import os
>>> os.__name__
216/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


'os'
>>> import random
>>> random.__name__
'random'

Sebuah nama spesial __main__ akan didefinisikan apabila modul dijalankan standalone. Dengan
memeriksa apakah __name__ == '__main__', kita bisa memeriksa apakah modul diimport atau
dijalankan standalone.

Contoh:
$ cat module1.py
#!/usr/bin/env python

if __name__ == '__main__':
print 'Dijalankan standalone'
else:
print 'Diimport'

$ python module1.py
Dijalankan standalone

>>> import module1


Diimport

Package
Modul-modul dapat dikelompokkan menjadi package. Berikut adalah beberapa catatan tentang
pembuatan package:
217/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Sebuah package terdiri dari sebuah direktori di file system. Secara opsional, direktori tersebut dapat
pula berisikan subdirektori-subdirektori.

Masing-masing subdirektori tersebut (apabila ada) mewakili subpackage.

Sebuah file spesial, __init__.py harus ada di dalam direktori agar direktori tersebut dianggap
sebagai package. File tersebut bisa saja berupa file kosong, atau dapat berisikan inisialisasi.

Sebuah variabel spesial __all__ (opsional; bertipe list) dapat ditentukan di dalam __init__.py, yang
pada akhirnya akan menentukan apa yang tersedia ketika package diimport dengan: from package
import *.

Contoh package1
package1
package1/__init__.py
package1/module2.py
package1/module1.py

>>> import package1.module1


>>> package1.module1.function1()
function 1
>>>

Contoh package2, dengan __all__


package2
package2/__init__.py
package2/module2.py
package2/module1.py

file __init__.py berisikan:

218/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


__all__ = ['module1']

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> from package2 import *
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'module1']
>>> module1.function1()
function 1
>>>

219/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.11 Exception
Kerjakan apa yang ingin dikerjakan, dan apabila terjadi kesalahan, kita siapkan handlernya.

Try...except...finally
Sintaks try...except...finally:

try:
<statement>
<statement>
...
except [expression [, target]]:
<statement>
<statement>
...
[else:
<statement>
<statement>
]
[finally:
<statement>
<statement>
]

Alur kerja:
Statement diantara try dan except akan dikerjakan

220/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Apabila tidak terdapat kesalahan, maka klausa except akan dilewati
Apabila terjadi kesalahan, sisa perintah yang masih ada di dalam try akan dilewati dan apabila
exception yang bersesuaian ditemukan, maka klausa except tersebut akan dikerjakan.
Apabila terjadi kesalahan namun tidak dihandle, maka secara otomatis, akan dilewatkan ke blok try
yang lebih luar, dan apabila tidak dihandle juga, maka kesalahan tersebut merupakan unhandled
exception dan eksekusi akan berhenti sesuai dengan kesalahannya.

Catatan:
Klausa else akan dikerjakan, apabila diberikan, dan tidak ada kesalahan yang terjadi. Berguna untuk
perintah yang akan dikerjakan apabila exception tidak terjadi.
try...except...finally berlaku mulai Python v2.5. Sebelumnya, try..except harus ditempatkan
bersarang di try...finally
Untuk menangani lebih dari satu exception pada satu waktu, deretkanlah ke dalam satu tuple (versi
2.6 ke atas).

Contoh tanpa exception:


>>> 1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

Contoh dengan exception sederhana:


>>> try:
...

1/0

... except ZeroDivisionError:


...

print 'Kesalahan: pembagian dengan nol'

...
Kesalahan: pembagian dengan nol
221/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Contoh dengan exception, melibatkan else:


>>> try:
...

1/1

... except ZeroDivisionError:


...

print 'Kesalahan: pembagian dengan nol'

... else:
...

print 'Tidak ada kesalahan yang terjadi'

...
1
Tidak ada kesalahan yang terjadi

Contoh dengan exception, else dan finally:


>>> try:
...

1/1

... except ZeroDivisionError:


...

print 'Kesalahan: pembagian dengan nol'

... else:
...

print 'Tidak ada kesalahan yang terjadi'

... finally:
...

print 'Pembagian selesai'

...
1
Tidak ada kesalahan yang terjadi
Pembagian selesai

222/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Try...finally
Sintaks try...finally

try:
<statement>
<statement>
...
finally:
<statement>
<statement>
...

Catatan:
try...finally berguna sebagai cleanup action, apapun kondisi yang terjadi.

Informasi exception
Apabila exception terjadi, informasi tertentu mungkin akan tersedia, sesuai dengan jenis exceptionnya.
Untuk mendapatkan, lewatkan argumen pada exception, seperti contoh berikut.

>>> try:
...

1/0

... except ZeroDivisionError, e:


...

print 'Kesalahan: ', e

...
Kesalahan: integer division or modulo by zero

223/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

Catatan:
Kita dapat pula mengakses atribut message apabila dibutuhkan. Contoh:
>>> try:
...

1/0

... except ZeroDivisionError, e:


...

print 'Kesalahan: ' + e.message

...
Kesalahan: integer division or modulo by zero

Membangkitkan exception
Untuk membangkitkan kesalahan tertentu, gunakanlah raise. Argumen opsional bisa diberikan.

>>> raise NameError


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError

>>> raise NameError, 'Ini detil kesalahan'


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: Ini detil kesalahan

224/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

10.12 File
Operasi file umumnya melibatkan pembukaan file, melakukan operasi tertentu, dan kemudian menutup
file terbuka tersebut.

Membuka dan menutup file


Untuk membuka file, gunakanlah fungsi:

open(path [,mode [,buffersize]])

Catatan:
path adalah path file yang ingin dibuka
mode dapat bernilai:
r: membuka file untuk dibaca
w: membuka file untuk ditulis. Apabila file yang ingin dibuka telah terdapat di filesystem,
maka isinya akan dihapus. Apabila file tidak ditemukan, maka akan dibuat secara otomatis.
a: membuka file untuk diupdate. Isi file yang sudah ada tidak dihapus.
r+: membuka file untuk dibaca dan ditulis. Isi file yang sudah ada tidak dihapus.
W+: membuka file untuk ditulis dan dibaca. Isi file yang sudah ada akan dihapus.
a+: membuka file untuk dibaca dan ditulis. Isi file yang sudah ada tidak dihapus.
b: apabila ditambahkan ke salah satu dari r, w, atau a, maka akan membuka file dalam modus
binary.
U: apabila ditambahkan ke salah satu dari r, w atau a, maka akan mengaplikasikan universal
newline. Newline pada setiap platform bisa berbeda-beda. Contoh: Linux menggunakan \n,
Windows menggunakan \r\n.
buffersize: ukuran buffer

225/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


Fungsi open yang berhasil akan mengembalikan objek file. Setelah digunakan, file tersebut harus
ditutup dengan method close() (kecuali pada statement with yang dibahas pada akhir bab ini).

Contoh:
>>> f = open('/etc/hosts')
>>> f
<open file '/etc/hosts', mode 'r' at 0xb7bf54e8>
>>> f.close()
>>> f
<closed file '/etc/hosts', mode 'r' at 0xb7bf54e8>
>>>

Membaca isi file


Untuk membaca isi file yang telah dibuka, beberapa cara bisa digunakan:
Membaca sekaligus isi file dengan method readlines(). Hasil pembacaan akan disimpan di list.

>>> f = open('/tmp/abc')
>>> isi = f.readlines()
>>> f.close()
>>> isi
['test baris 1\n', 'test baris 2\n', 'test baris 3\n']
>>>

Membaca sekaligus isi file dengan method read(). Hasil pembacaan akan disimpan di string.

>>> f = open('/tmp/abc')

226/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> isi = f.read()
>>> f.close()
>>> isi
'test baris 1\ntest baris 2\ntest baris 3\n'

Membaca baris demi baris dengan method readline().

>>> f = open('/tmp/abc')
>>> while True:
...

baris = f.readline()

...

if not baris:

...

break

...

print baris

...
test baris 1

test baris 2

test baris 3

>>> f.close()
>>>

Membaca langsung baris tertentu dengan module linecache.


>>> import linecache
>>> baris2 = linecache.getline('/tmp/abc',2)

227/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus


>>> print baris2
test baris 2

>>> linecache.clearcache()

Membaca sejumlah byte tertentu dengan method read().

>>> f = open('/tmp/abc')
>>> buf3 = f.read(3)
>>> print buf3
tes
>>> f.close()
>>>

Menulis ke file
Untuk menulis ke file yang telah dibuka, beberapa cara bisa digunakan:
Menulis string dengan method write.

>>> f = open('/tmp/test','w')
>>> f.write('halo apa kabar')
>>> f.close()
>>>
>>> print open('/tmp/test').readlines()
['halo apa kabar']

Menulis sequence dengan method writelines.


228/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

>>> lines = ['halo', 'apa', 'kabar']


>>> f = open('/tmp/test2', 'w')
>>> f.writelines(lines)
>>> f.close()
>>>
>>> print open('/tmp/test2').readlines()
['haloapakabar']
>>>

Statement with
Pada python versi 2.5, statement with diperkenalkan sebagai fitur opsional, dimana untuk
menggunakannya, kita melakukan:

from __future__ import with_statement

Pada python versi 2.6, statement with bisa langsung dipergunakan.

with expression [as variable]:


with-block

Statement ini dapat digunakan untuk memastikan kode untuk melakukan clean-up akan dikerjakan,
seperti halnya pada try/finally. Dan, ini berlaku untuk object yang mendukung context management
protocol.

Contoh yang mendukung adalah file. Dengan demikian, kita bisa bekerja dengan file dengan cara
berikut:

229/232

Dasar-dasar OpenERP: sisi teknikal dan contoh kasus

>>> with open('/tmp/test.txt') as f:


...

for line in f:

...

print line

...

Objek file f dalam contoh tersebut akan ditutup secara otomatis.

230/232

Anda mungkin juga menyukai