[Odoo 10] Technical Documentation -Part 11-

Alhamdulillah akhirnya kita berada di penghujung tutorial ini. Serial technical documentation ini insya Allah akan saya akhiri pada pertemuan kali ini dengan pembahasan reporting pada Odoo. Ada banyak tools yang bisa kita gunakan untuk membuat report pada Odoo 10 seperti Jasper, webkit, dll. Tetapi saya akan cukupkan pembahasan dengan report default yang telah Odoo sediakan yaitu RML dan QWEB.

Sebelum kita masuk ke pembahasan utama yaitu report. Sedikit kita bahas tentang state pada Odoo. Seperti penjelasan pada artikel sebelumnya, workflow telah di hapus semenjak v10 dan ‘dicukupkan’ dengan state. Untuk object training ini, kita akan tambahkan 3 state yaitu draft, open, dan done. Awalan kita update class Kursus() menjadi :



class Kursus(models.Model):
    _name = 'training.kursus'

    ...

    state = fields.Selection([
        ('draft', 'Draft'),
        ('open', 'Open'),
        ('done', 'Done'),
        ], string='Status', readonly=True, copy=False, default='draft')
    
 
    @api.multi
    def action_confirm(self):
        self.write({'state': 'open'})

    @api.multi
    def action_cancel(self):
        self.write({'state': 'draft'})

    @api.multi
    def action_close(self):
        self.write({'state': 'done'})


Pada code diatas, kita membuat sebuah field yaitu state dan 3 method yaitu action_confirm(), action_cancel(), dan action_close(). Fungsi dari 3 method tersebut berfungsi hanya untuk merubah sebuah nilai field state. Dan ketiga method tersebut akan di panggil oleh 3 button yang berbeda. Sekarang kita sesuaikan view dari penambahan field dan button seperti berikut :



    	
	<!-- ### Membuat Tampilan Tree/List Kursus ### -->
	
	<record model="ir.ui.view" id="kursus_tree_view">
	    <field name="name">training.kursus.tree</field>
	    <field name="model">training.kursus</field>
	    <field name="arch" type="xml">
	        <tree string="Kursus List">
	            <field name="name"/>
	            <field name="responsible_id"/>
	            <field name="description"/>
	            <field name="state"/>       
	        </tree>
	    </field>
	</record>
	
	

	<!-- ### Membuat Tampilan Form Kursus ### -->
	
	<record model="ir.ui.view" id="kursus_form_view">
	    <field name="name">training.kursus.form</field>
	    <field name="model">training.kursus</field>
	    <field name="arch" type="xml">
	        <form string="Kursus Form">
	        	<header>
                    <button name="action_confirm" type="object" string="Confirm" states="draft" class="btn-primary"/>
                    <button name="action_cancel" type="object" string="Cancel" states="open"/>
                    <button name="action_close" type="object" string="Close" states="open" class="btn-primary"/>
                    <field name="state" widget="statusbar" statusbar_visible="draft,open,done"/>
                </header>
	            <sheet>
	                <group>
	                    <field name="name"/>
	            		<field name="responsible_id"/>
	                </group>
	                <notebook>
	                    <page string="Sesi">
							<field name="session_ids">
								<tree string="Daftar Sesi" editable="bottom">
									<field name="name"/>
									<field name="instructor_id"/>
								</tree>
								<form>
									<group string="Informasi">
										<field name="name"/>
										<field name="instructor_id"/>
									</group>
									<group string="Jadwal">
										<field name="start_date"/>
										<field name="duration"/>
										<field name="seats"/>
									</group>
								</form>
							</field>
						</page>
	                    <page string="Keterangan">
	                        <field name="description"/>
	                    </page>
	                </notebook>
	            </sheet>
	        </form>
	    </field>
	</record>
		

Perubahan coding diatas hanya merubah field state, sedangkan kita juga ingin mempengaruhi field-field yang lain. Yaitu ketika statenya berubah maka field yang lain menjadi readonly. Untuk merealisasikan hal tersebut, maka kita harus menambahkan attribute state dan readonly pada setiap field sehingga hasilnya seperti berikut :



class Kursus(models.Model):
    _name = 'training.kursus'

    name = fields.Char(string="Judul", required=True, readonly=True, states={'draft': [('readonly', False)]})
    description = fields.Text(readonly=True, states={'draft': [('readonly', False)]})
    session_ids = fields.One2many('training.sesi', 'course_id', string="Sesi", readonly=True, states={'draft': [('readonly', False)]})
    responsible_id = fields.Many2one('res.users', ondelete='set null', string="Penanggung Jawab", index=True, readonly=True, states={'draft': [('readonly', False)]})


Status Draft

Status Open

Untuk selanjutnya kita akan menambahkan log history perubahan yang dilakukan user pada object kursus kita yang biasanya berada di bawah form, seperti form sales order. Sebelumnya pastikan kita telah menginstall modul Discuss (mail). Update file __manifest__.py :


'depends': ['base', 'mail'],

Lanjutkan dengan update di class kursus() kita :



class Kursus(models.Model):
    _name = 'training.kursus'
    _inherit = 'mail.thread'
    

    name = fields.Char(string="Judul", required=True, readonly=True, states={'draft': [('readonly', False)]}, track_visibility='always')
    description = fields.Text(readonly=True, states={'draft': [('readonly', False)]}, track_visibility='onchange')
    session_ids = fields.One2many('training.sesi', 'course_id', string="Sesi", readonly=True, states={'draft': [('readonly', False)]}, track_visibility='onchange')
    responsible_id = fields.Many2one('res.users', ondelete='set null', string="Penanggung Jawab", index=True, readonly=True, states={'draft': [('readonly', False)]}, track_visibility='onchange')
    state = fields.Selection([
        ('draft', 'Draft'),
        ('open', 'Open'),
        ('done', 'Done'),
        ], string='Status', readonly=True, copy=False, default='draft', track_visibility='onchange')

...

Kita membutuhkan class mail.thread() untuk mengadopsi log history dan attribute track_visibility, kemudian kita update file xml viewnya :



	<!-- ### Membuat Tampilan Form Kursus ### -->
	
	<record model="ir.ui.view" id="kursus_form_view">
	    <field name="name">training.kursus.form</field>
	    <field name="model">training.kursus</field>
	    <field name="arch" type="xml">
	        <form string="Kursus Form">
	        	<header>
                    <button name="action_confirm" type="object" string="Confirm" states="draft" class="btn-primary"/>
                    <button name="action_cancel" type="object" string="Cancel" states="open"/>
                    <button name="action_close" type="object" string="Close" states="open" class="btn-primary"/>
                    <field name="state" widget="statusbar" statusbar_visible="draft,open,done"/>
                </header>
	            <sheet>
	                <group>
	                    <field name="name"/>
	            		<field name="responsible_id"/>
	                </group>
	                <notebook>
	                    <page string="Sesi">
							<field name="session_ids">
								<tree string="Daftar Sesi" editable="bottom">
									<field name="name"/>
									<field name="instructor_id"/>
								</tree>
								<form>
									<group string="Informasi">
										<field name="name"/>
										<field name="instructor_id"/>
									</group>
									<group string="Jadwal">
										<field name="start_date"/>
										<field name="duration"/>
										<field name="seats"/>
									</group>
								</form>
							</field>
						</page>
	                    <page string="Keterangan">
	                        <field name="description"/>
	                    </page>
	                </notebook>
	            </sheet>
                <div class="oe_chatter">
                    <field name="message_follower_ids" widget="mail_followers"/>
                    <field name="message_ids" widget="mail_thread"/>
                </div>
	        </form>
	    </field>
	</record>
	

Silahkan lakukan perubahan (edit) lalu perhatikan field yang berattribute track_visibility=’onchange‘ dan track_visibility=’always‘. Sekarang kita akan membuat report RML pada object kursus, lakukan perubahan seperti berikut :

A. Buat folder report
B. Lalu buat file __init__.py di dalam folder report dengan isi :


import report

C. Buat file report.py dengan isi :


import time
from openerp.report import report_sxw

class print_training(report_sxw.rml_parse):
    def __init__(self, cr, uid, name, context):
        super(print_training, self).__init__(cr, uid, name, context=context)
        self.localcontext.update({
            'time': time,            
        })

report_sxw.report_sxw('report.laporan.kursus', 'training.kursus', 'addons/training_odoo/report/print_kursus.rml', parser=print_training, header=False)


D. Buat file report_view.xml dengan isi :


<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>
        

	<report id="cetak_kursus" string="Report RML" 
			model="training.kursus" name="laporan.kursus" 
			rml="training_odoo/report/print_kursus.rml"
			auto="False" menu="False"/>
    	
    	
    </data>
</odoo>

Fungsi baris code diatas adalah untuk membuat action dari button report yang akan kita buat.

E. Buat file template report print_kursus.rml yang isinya :


<?xml version="1.0"?>
<document filename="Form Kursus.pdf">
 
  <!-- DEFINISI LAYOUT (Ukuran Kertas) -->
   
  <template pageSize="(595.0, 842.0)" title="Report Kursus" author="Radio Rodja 756 am (http://radiorodja.com)">
    <pageTemplate id="first">
         
      <!-- Menentukan luas dari canvas yang dapat kita 'tulis' dengan parameter widht & height beserta titik awal penulisan identasi/margin -->
  
      <frame id="first" x1="20.0" y1="485.0" width="538" height="350"/>
      
      <header>
            <!-- Membuat text/image sesuai dengan presisi yang tepat dengan menggunakan titik koordinat -->
            <pageGraphics>
                <setFont name="Helvetica" size="6"/>
                <drawString x="19.0cm" y="1cm"> <pageNumber/></drawString>
            </pageGraphics>      
      </header>
        
    </pageTemplate>
  </template>
   
  <!-- DEFINISI STYLE -->
   
  <stylesheet>
 
 
    <!-- Mendefiniskan Style Tabel -->
     
    <blockTableStyle id="Table_String">
      <blockAlignment value="LEFT"/>
      <blockValign value="TOP"/>
    </blockTableStyle>
 
     
    <blockTableStyle id="Tabel_Sesi">
      <blockAlignment value="LEFT"/>
      <blockValign value="TOP"/>
        <!-- Kolom ke-1 -->
        <!-- atas --><lineStyle kind="LINEABOVE" colorName="#000000" start="0,0" stop="0,0"/>
        <!-- kanan --><lineStyle kind="LINEBEFORE" colorName="#000000" start="1,-1" stop="1,-1"/>
        <!-- bawah --><lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
        <!-- kiri --><lineStyle kind="LINEBEFORE" colorName="#000000" start="0,0" stop="0,0"/>
        <!-- Kolom ke-2 -->
        <!-- atas --><lineStyle kind="LINEABOVE" colorName="#000000" start="1,0" stop="1,0"/>
        <!-- kanan --><lineStyle kind="LINEBEFORE" colorName="#000000" start="2,-1" stop="2,-1"/>
        <!-- bawah --><lineStyle kind="LINEBELOW" colorName="#000000" start="1,-1" stop="1,-1"/>
        <!-- kiri --><lineStyle kind="LINEBEFORE" colorName="#000000" start="1,0" stop="1,0"/>
    </blockTableStyle>
     
    <initialize>
      <paraStyle name="all" alignment="justify"/>
    </initialize>
        
    <!-- Mendefinisikan Style Huruf -->
     
    <paraStyle name="terp_header" fontName="Helvetica-Bold" fontSize="12.0" leading="15" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
    <paraStyle name="terp_table_header" fontName="Helvetica-Bold" fontSize="7.0" leading="8" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
    <paraStyle name="terp_default" fontName="Helvetica" fontSize="7.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
     
    <images/>
  </stylesheet>
   
  <!-- DEFINISI DATA -->
  <story>
  <pto>
  
    <!-- DEFINISI OBJECT ALIAS -->
   
    <para style="terp_default">[[repeatIn(objects, 'kursus')]] </para>
 
 
    <!-- Membuat Judul Report -->
      
    <blockTable colWidths="500.0" style="Table_String">
      <tr><td><para style="terp_header">REPORT KURSUS</para></td></tr>
    </blockTable>
 
    <!-- Membuat Header Report -->
     
    <blockTable colWidths="330.0,170.0" style="Table_String">
      <tr>
        <td>
          <para style="terp_default">Judul Kursus : [[ kursus.name ]]</para>
        </td>
        <td>
          <para style="terp_default">Penanggung Jawab : [[ kursus.responsible_id.name ]]</para>
        </td>
      </tr>
    </blockTable>
     
    <!-- Membuat Gap/Space Baris Kosong -->
     
    <para style="terp_default"><font color="white">.</font></para>
     
    <!-- Membuat Header Tabel Sesi -->
     
    <blockTable colWidths="350.0,150.0" repeatRows="1" style="Tabel_Sesi">
      <tr>
        <td><para style="terp_table_header">Nama</para></td>
        <td><para style="terp_table_header">Instruktur</para></td>
      </tr>
    </blockTable>
     
    <!-- Membuat Looping Data Tabel Sesi (Element Section) -->
     
    <section>
       
      <para style="terp_default">[[ repeatIn(kursus.session_ids, 'x') ]]</para>
       
      <blockTable colWidths="350.0,150.0" repeatRows="0" style="Tabel_Sesi">
        <tr>
          <td><para style="terp_default">[[ x.name ]]</para></td>
          <td><para style="terp_default">[[ x.instructor_id.name ]]</para></td>
        </tr>
      </blockTable>
       
    </section>
     
  </pto>
  </story>
</document>

F. Update file __init__.py di folder training_odoo (yang sejajar dengan __manifest__.py):


from . import controllers
from . import models
from . import wizard
from . import report

G. Update file __manifest__.py :


    # always loaded
    'data': [
        'report/report_view.xml',
        'security/security.xml',
        'security/ir.model.access.csv',
        'views/views.xml',
        'views/templates.xml',
        'views/partner.xml',
        'wizard/wizard_view.xml',
    ],

Terakhir kita buat button untuk mengenerate report di form kursus :

H. Update form kursus sebagai berikut :



	
	<!-- ### Membuat Tampilan Form Kursus ### -->
	
	<record model="ir.ui.view" id="kursus_form_view">
	    <field name="name">training.kursus.form</field>
	    <field name="model">training.kursus</field>
	    <field name="arch" type="xml">
	        <form string="Kursus Form">
	        	<header>
                    <button name="action_confirm" type="object" string="Confirm" states="draft" class="btn-primary"/>
                    <button name="action_cancel" type="object" string="Cancel" states="open"/>
                    <button name="action_close" type="object" string="Close" states="open" class="btn-primary"/>
                    <button name="%(cetak_kursus)d" type="action" states="done" string="Report RML"/>
                    <field name="state" widget="statusbar" statusbar_visible="draft,open,done"/>
                </header>
	            <sheet>
	                <group>
	                    <field name="name"/>
	            		<field name="responsible_id"/>
	                </group>
	                <notebook>
	                    <page string="Sesi">
							<field name="session_ids">
								<tree string="Daftar Sesi" editable="bottom">
									<field name="name"/>
									<field name="instructor_id"/>
								</tree>
								<form>
									<group string="Informasi">
										<field name="name"/>
										<field name="instructor_id"/>
									</group>
									<group string="Jadwal">
										<field name="start_date"/>
										<field name="duration"/>
										<field name="seats"/>
									</group>
								</form>
							</field>
						</page>
	                    <page string="Keterangan">
	                        <field name="description"/>
	                    </page>
	                </notebook>
	            </sheet>
                <div class="oe_chatter">
                    <field name="message_follower_ids" widget="mail_followers"/>
                    <field name="message_ids" widget="mail_thread"/>
                </div>
	        </form>
	    </field>
	</record>
	
	

Hasilnya seperti ini :

Selanjutnya kita akan membuat report QWEB pada object sesi, ikuti langkah-langkah berikut :

A. Buat button report di form sesi



	<!-- ### Membuat Tampilan Form Sesi ### -->
		
	<record model="ir.ui.view" id="sesi_form_view">
		<field name="name">training.sesi.form</field>
		<field name="model">training.sesi</field>
		<field name="arch" type="xml">
			<form string="Sesi Form">
				<header>
                    <button name="cetak_sesi" string="Report QWEB" type="object" class="btn-primary"/>
                </header>
	            <sheet>
					<group>
						<group string="Informasi">
							<field name="course_id"/>
							<field name="name"/>
							<field name="instructor_id"/>
							<field name="seats"/>							
						</group>
						<group string="Jadwal">
							<field name="start_date"/>
							<field name="duration"/>
							<field name="end_date"/>
							<field name="taken_seats" widget="progressbar"/>							
						</group>
						<group string="Peserta" colspan="2">
							<field name="attendee_ids" nolabel="1"/>
						</group>						
					</group>
				</sheet>
			</form>
		</field>
	</record>
	
	

B. Buat method dari button report diatas (karna typenya object) pada class sesi :


class Sesi(models.Model):
    _name = 'training.sesi'
    
    ....

    @api.multi
    def cetak_sesi(self):
        return self.env['report'].get_action(self, 'training_odoo.laporan_sesi')

C. Buat action yang akan di panggil dari method button diatas pada file report_view.xml :

			
    <report 
        id="cetak_sesi"
        string="Report QWEB"
        model="training.sesi" 
        report_type="qweb-pdf"
        file="training_odoo.laporan_sesi" 
        name="training_odoo.laporan_sesi" 
    />    	


D. Buat file template report didalam folder report dengan nama print_sesi.xml yang isinya :


<?xml version="1.0" encoding="utf-8"?>
<odoo>
	
	
<template id="laporan_sesi">
    <t t-call="report.html_container">
    	<t t-foreach="docs" t-as="o">
	        <t t-call="report.external_layout">
		        <div class="page">
		            
					<!-- JUDUL REPORT-->
					
		            <h2 class="text-center">REPORT SESI</h2>
		
		            <!-- INFORMASI HEADER -->
		            
                    <table class="table">
                        <tr>
                            <td><strong>Nama</strong></td>
                            <td><span t-field="o.name"/></td>
                            <td><strong>Instruktur</strong></td>
                            <td><span t-field="o.instructor_id.name"/></td>
                        </tr>
                        <tr>
                            <td><strong>Tanggal Mulai</strong></td>
                            <td><span t-field="o.start_date"/></td>
                            <td><strong>Tanggal Akhir</strong></td>
                            <td><span t-field="o.end_date"/></td>
                        </tr>
                    </table>
		            
		
		            
		            <table class="table table-bordered" style="table-layout:auto">
		                <thead>
		                    <tr>
		                        <th class="text-center">Name</th>
		                        <th class="text-center">Phone</th>
		                        <th class="text-center">Email</th>
		                    </tr>
		               </thead>
		               <tbody>
		                    <t t-foreach="o.attendee_ids" t-as="l">
		                        <tr>
		                            <td><span t-field="l.name"/></td>
		                            <td><span t-field="l.phone"/></td>
		                            <td><span t-field="l.email"/></td>
		                        </tr>
		                    </t>
		                </tbody>
		            </table>
		
		        </div>
			</t>
		</t>
    </t>
</template>

</odoo>


E. Update file _manifest__.py :


    # always loaded
    'data': [
        'report/report_view.xml',
        'report/print_sesi.xml',
        'security/security.xml',
        'security/ir.model.access.csv',
        'views/views.xml',
        'views/templates.xml',
        'views/partner.xml',
        'wizard/wizard_view.xml',
    ],

Report yang dihasilkan seperti berikut :

Alhamdulillah wa syukurillah, akhirnya kita telah menyelesaikan serial tutorial technical ini, bagi yang mengalami kendala, bisa mendownload hasil tulisan ini disini.

Yang benar datangnya dari Allah azza wa jalla, sedangkan kesalahan dari saya pribadi.
Saran dan kritik yang membangun sangat saya harapkan.
Semoga bermanfaat.

Wassalamu’alaikum….

Advertisements

Leave a Reply

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

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s