Model pada OpenERP

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):

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

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' :

id1= 'partner_id' , id2= 'category_id' , string= 'Tags' ),

fields.many2many( 'res.partner.category' ,

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 ): def _function_test(self, cr, uid, ids, field, arg, context= None ):

_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)

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.

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:

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

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.

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

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.

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).

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 openerp/addons/sale/sale.py: Python script, ASCII text executable, with very long

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.

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,

>>> 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,

>>> 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', '=', '')

Dan, kita tempatkan pada sebuah list: ['&', '|', ('name', 'ilike', 'tes'), ('id', '<', 3), ('website', '=', '')]

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} >>>

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} >>>

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.

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() >>>

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' ], { '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' ],

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>

<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>

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' ], { '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' ],

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>

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' ], { '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' ],

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>

</record> </data>

</openerp>

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

<?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>

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)