Belajar Odoo Untuk Pemula [Part 8/8]

Inheritance

Model Inheritance

Odoo menyediakan dua mekanisme inheritance untuk memperluas model yang ada dengan cara yang modular.

Pertama, memungkinkan modul untuk memodifikasi behavior model yang didefinisikan pada modul lain, seperti :

  • Menambahkan field
  • Menambahkan constraint
  • Menambahkan method
  • Override field yang ada di model lain (mengubah attribute)
  • Override method di model lain
  • dll

Kedua, pendelegasian yang memungkinkan untuk menghubungkan semua record model terhadap parent model. Jenis kedua ini ditulis dengan syntax _inherits seperti yang sudah dibahas di part sebelumnya.

View Inheritance

View inheritance memungkinkan kita untuk menambah, memodifikasi ataupun menghapus tampilan view yang didefinisikan di parent nya.

View inheritance me refer ke parent menggunakan inherit_id. Setelah itu kita bisa memodifikasi isi dari view parent dengan menggunakan position.

<record id="ms_ir_module_module_search_view" model="ir.ui.view">
    <field name="name">ms.ir.module.module.search</field>
    <field name="model">ir.module.module</field>
    <field name="inherit_id" ref="base.view_module_filter"/>
    <field name="arch" type="xml">
 
        <field name="name" position="after">
            <field name="author"/>
            <field name="website"/>
            <filter name="filter_miftah" string="New Addons" domain="[('author','=','Miftahussalam')]"/>
        </field>
 
    </field>
</record>

position bisa berisi beberapa value :

  • inside : akan menempatkan field/button baru di akhir elemen yang cocok
  • replace : akan mereplace/meremove field/button dari model parent
  • before : akan menempatkan field/button baru sebelum elemen
  • after : akan menempatkan field/button baru setelah elemen
  • attributes : mengubah atribut dari elemen yang cocok dengan elemen atribut khusus yang ditambahkan

Praktek

Contoh inherit untuk menambahkan method salah satunya ada pada file ms_base/models/ir_sequence.py

Method tersebut ditambahkan untuk memudahkan pembuatan nomor sequence yang dipanggil di semua form transaksi (contoh: DFT/18/00005).

Pada file ms_puskesmas/models/res_partner.py inherit ke model res.partner dengan tujuan untuk menambahkan fields, constraint dan override method.

Selain menambahkan field kita juga bisa mengubah attribute fields dengan cara menulis ulang field beserta type nya yang sudah ada di model parent, dan kita hanya perlu menuliskan attribute yang mau diubah atau ditambahkan. Misal kita akan menggunakan field city di res.partner akan tetapi string nya mau diubah menjadi ‘Kota’, seperti ini :

Pertama-tama kita tambahkan field city di xml pada file ms_puskesmas/views/res_partner.xml di bagian record id “ms_pasien_form_view”

Terlihat pada tampilan aplikasi stringnya adalah ‘City’, kemudian kita akan ubah menjadi ‘Kota’. Untuk melakukan itu sebenarnya ada dua cara. Pertama ubah di xml dengan menggunakan attributes seperti yang diterapkan untuk field street di atas. Kedua ubah di py seperti yang akan kita praktekkan sekarang.

Masih di file res_partner.py tambahkan field :

city = fields.Char(string='Kota')

Silahkan restart service dan upgrade, maka string filed city akan berubah menjadi ‘Kota’

Pada ms_base/views/ir_module_module.xml merupakan contoh inherit view view_module_filter (tempat install addons pada menu Apps) untuk menambahkan field author, website dan filter, serta membuat default filter agar ketika klik menu Apps maka sudah otomatis ter filter hanya addons custom yang muncul.

Selanjutnya kita akan coba praktekkan mekanisme inheritance yang kedua, yaitu pendelegasian dengan menggunakan syntax _inherits.

Kita akan buat model master baru, yaitu model ms.room

Silahkan buat file baru di ms_puskesmas/models dengan nama ms_room.py dan isi dengan syntax berikut

from odoo import fields, api, models

class ms_room(models.Model):
    _name = "ms.room"
    _description = "Poli"
 
    name = fields.Char('Nama', required=True)
    kode = fields.Char('Kode', required=True, copy=False)
    posisi = fields.Char('Posisi Ruangan')

    _sql_constraints = [
        ('unique_kode', 'unique(kode)', 'Kode Poli duplicate, mohon cek kembali !'),
    ]
 
    @api.multi
    def name_get(self):
        result = []
        for me in self :
            if me.posisi :
                result.append((me.id, "%s - %s" % (me.posisi, me.name)))
            else :
                result.append((me.id, me.name))
        return result
 
    @api.model
    def name_search(self, name, args=None, operator='ilike', limit=100):
        args = args or []
        if name :
            recs = self.search([
                '|',
                ('posisi', operator, name),
                ('name', operator, name),
            ] + args, limit=limit)
        else :
            recs = self.search([] + args, limit=limit)
        return recs.name_get()

dan di ms_puskesmas/views dengan nama ms_room.xml

<odoo>
    <data>
 
        <record model="ir.ui.view" id="ms_room_tree_view">
            <field name="name">ms.room.tree</field>
            <field name="model">ms.room</field>
            <field name="arch" type="xml">
                <tree string="Ruangan" editable="top">
                    <field name="kode"/>
                    <field name="name"/>
                    <field name="posisi"/>
                </tree>
            </field>
        </record>
 
        <record id="view_ms_room_search" model="ir.ui.view">
            <field name="name">ms.room.search</field>
            <field name="model">ms.room</field>
            <field name="arch" type="xml">
                <search string="Search Ruangan">
                    <field name="name"/>
                    <field name="kode"/>
                    <field name="posisi"/>
                </search>
            </field>
        </record>
 
        <record model="ir.actions.act_window" id="ms_room_action">
            <field name="name">Ruangan</field>
            <field name="res_model">ms.room</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree,form</field>
            <field name="context">{}</field>
            <field name="domain">[]</field>
        </record>
 
        <record id="ms_room_action_tree" model="ir.actions.act_window.view">
            <field eval="1" name="sequence"/>
            <field name="view_mode">tree</field>
            <field name="view_id" ref="ms_room_tree_view"/>
            <field name="act_window_id" ref="ms_room_action"/>
        </record>
 
        <menuitem action="ms_room_action" id="ms_room_menu" parent="ms_base.ms_data_master_submenu" sequence="25"/>
 
    </data>
</odoo>

Jangan lupa tambah import ms_room di ms_puskesmas/models/__init__.py dan update __manifest__.py untuk membaca file ms_puskesmas.xml

Kemudian update isi file ms_poli.py dan ms_poli.xml seperti berikut :

ms_poli.py

from odoo import fields, api, models

class ms_poli(models.Model):
    _name = "ms.poli"
    _description = "Poli"
    _inherits = {'ms.room': 'room_id'}
 
    room_id = fields.Many2one('ms.room', string='Ruangan', ondelete='restrict', required=True, auto_join=True)
    name = fields.Char(related='room_id.name', inherited=True)
    kode = fields.Char(related='room_id.kode', inherited=True)
 
    @api.multi
    def name_get(self):
        result = []
        for me in self :
            result.append((me.id, "%s - %s" % (me.kode, me.name)))
        return result
 
    @api.model
    def name_search(self, name, args=None, operator='ilike', limit=100):
        args = args or []
        if name :
            recs = self.search([
                '|',
                ('kode', operator, name),
                ('name', operator, name),
            ] + args, limit=limit)
        else :
            recs = self.search([] + args, limit=limit)
        return recs.name_get()

ms_poli.xml

<odoo>
    <data>

        <record model="ir.ui.view" id="ms_poli_tree_view">
            <field name="name">ms.poli.tree</field>
            <field name="model">ms.poli</field>
            <field name="arch" type="xml">
                <tree string="Poli">
                    <field name="kode"/>
                    <field name="name"/>
                    <field name="room_id" readonly="1" attrs="{'invisible': [('id','=',False)]}"/>
                    <field name="id" invisible="1"/>
                </tree>
            </field>
        </record>

        <record model="ir.ui.view" id="ms_poli_form_view">
            <field name="name">ms.poli.form</field>
            <field name="model">ms.poli</field>
            <field name="arch" type="xml">
 
                <form string="Poli">
                    <sheet>
                        <group col="4">
                            <field name="kode"/>
                            <field name="name"/>
                            <field name="room_id" readonly="1" attrs="{'invisible': [('id','=',False)]}" required="0"/>
                            <field name="id" invisible="1"/>
                        </group>
                    </sheet>
                </form>
 
            </field>
        </record>

        <record id="view_ms_poli_search" model="ir.ui.view">
            <field name="name">ms.poli.search</field>
            <field name="model">ms.poli</field>
            <field name="arch" type="xml">
                <search string="Search Poli">
                    <field name="name"/>
                    <field name="kode"/>
                    <field name="room_id"/>
                </search>
            </field>
        </record>

        <record model="ir.actions.act_window" id="ms_poli_action">
            <field name="name">Poli</field>
            <field name="res_model">ms.poli</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree,form</field>
            <field name="context">{}</field>
            <field name="domain">[]</field>
        </record>
 
        <record id="ms_poli_action_tree" model="ir.actions.act_window.view">
            <field eval="1" name="sequence"/>
            <field name="view_mode">tree</field>
            <field name="view_id" ref="ms_poli_tree_view"/>
            <field name="act_window_id" ref="ms_poli_action"/>
        </record>

        <record id="ms_poli_action_form" model="ir.actions.act_window.view">
            <field eval="1" name="sequence"/>
            <field name="view_mode">form</field>
            <field name="view_id" ref="ms_poli_form_view"/>
            <field name="act_window_id" ref="ms_poli_action"/>
        </record>

        <menuitem action="ms_poli_action" id="ms_poli_menu" parent="ms_base.ms_data_master_submenu" sequence="30"/>

    </data>
</odoo>

Silahkan upgrade modul sehingga muncul menu baru di Data Master yaitu menu Ruangan

Jika belum berhasil/error silahkan ambil source code berikut puskesmas branch lanjut

ms.poli menginherits ms.room sehingga setiap create Poli baru maka akan otomatis membuat Ruangan baru dengan nama dan kode yang sama. Tapi tidak berlaku sebaliknya, ketika membuat ruangan baru tidak akan otomatis membuat poli. Karena setiap poli pasti membutuhkan ruangan, tapi tidak setiap ruangan ditujukan untuk poli.

Silahkan lakukan testing dengan membuat poli baru

Note : Jika sebelumnya master poli sudah terdapat record maka akan ada error akses. Cara mengatasinya silahkan hapus semua record poli lewat pgAdmin.

Berikut contoh penginputannya

Alhamdulillah, kita sudah menyelesaikan materi dasar odoo teknikal. Saya rasa jika anda sudah memahami materi-materi yang disampaikan dari part 1-8 ini maka sudah cukup untuk menumbuhkan benih-benih cinta terhadap odoo 😀

Saran saya setelah ini anda harus mempelajari satu materi lagi yang belum dibahas di serial ini dan cukup penting ketika implementasi, yaitu mengenai hak akses. Dan insya Allah di lain waktu saya juga akan membahasnya di blog ini.

Saya menyadari tutorial ini masih banyak kekurangan, dan insya Allah saya akan terus mengupdate dan melengkapinya agar lebih mudah difahami. Kemudian jika yang saya sampaikan terdapat kekeliruan mohon beri tahu saya karena saya juga masih belajar.

Terimakasih, semoga bermanfaat dan CMIIW…

Tutorial odoo/openerp Indonesia