Fill PDF Form

slide-jamsostek

Seiring berjalannya waktu implementasi, beraneka ragam jenis report harus bisa di provide oleh OpenERP. Diantaranya adalah report jamsostek yang sudah memiliki template form sesuai kebutuhan di indonesia. Report jenis ini biasanya banyak digunakan ketika kita implementasi modul HR, karna pada modul ini banyak sekali customisasi terkait localisasi di Indonesia. In syaa Allah pada tutorial kali ini kita akan mempelajari cara membuat report tersebut dan mengaplikasikannya pada kebutuhan kita masing-masing.

Hal pertama yang kita butuhkan adalah file pdf yang akan kita jadikan sebagai form, misalnya adalah file pdf jamsostek. Setelah itu kita edit file pdf jamsostek menggunakan adobe acrobat sehingga hasilnya seperti ini. Bagaimana cara membuatnya, silahkan googling ya 😀

Setelah kita memiliki pdf form yang sudah siap, selanjutnya kita tentukan report ini akan dicetak pada form employee dengan membuat sebuah button actionnya. Selanjutnya seperti biasa kita buat sebuah modul OpenERP, lalu kita tambahkan code button yang akan disisipkan pada form employee yang bertujuan untuk mencetak report tersebut. Contoh codenya seperti dibawah ini:



		<record model="ir.ui.view" id="hr_employee_form_view_jamsostek">
            <field name="name">hr.employee.jamsostek</field>            
            <field name="model">hr.employee</field>            
            <field name="inherit_id" ref="hr.view_employee_form"/>
            <field name="arch" type="xml">
                <xpath expr="//sheet" position="before">
                	<header>
                        <button name="print_jamsostek" type="object" string="Jamsostek" icon="gtk-print"/>
	           		</header>                                
				</xpath>
            </field>		
		</record>


Setelah button kita buat, selanjutnya kita buat method yang akan ditriger dari button tersebut yaitu method print_jamsostek(). Contoh codenya seperti ini :



from osv import osv

class hr_employee(osv.osv):
    _inherit = 'hr.employee'
        
    def print_jamsostek(self, cr, uid, ids, context=None):
        data = {}
        data['form'] = {}
        data['ids'] = context.get('active_ids',[])
        data['form']['data'] = self.read(cr, uid, ids)[0]
        
        return {
                'type': 'ir.actions.report.xml', 
                'report_name': 'form.jamsostek', 
                'datas': data, 
                'nodestroy':True
        }

hr_employee()


Method diatas mungkin tidak perlu saya jelaskan, silahkan mereview tutorial sebelumnya yang membahas tentang report.

Langkah selanjutnya kita buat 1 folder bernama report (didalam modul), folder report ini akan berisi 4 file, diantaranya :

1. File pdf jamsostek yang diawal sudah kita siapkan
2. File __init__.py yang isinya seperti ini:


import print_pdf

3. File pdf_ext.py yang merupakan library untuk memanipulasi pdf, isinya sebagai berikut:


# -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

""" Copyright (c) 2003-2007 LOGILAB S.A. (Paris, FRANCE).
 http://www.logilab.fr/ -- mailto:contact@logilab.fr

manipulate pdf and fdf files. pdftk recommended.

Notes regarding pdftk, pdf forms and fdf files (form definition file)
fields names can be extracted with:
    pdftk orig.pdf generate_fdf output truc.fdf
to merge fdf and pdf:
    pdftk orig.pdf fill_form test.fdf output result.pdf [flatten]
without flatten, one could further edit the resulting form.
with flatten, everything is turned into text.
"""

import os
import tools

HEAD="""%FDF-1.2
%\xE2\xE3\xCF\xD3
1 0 obj
<<
/FDF
<<
/Fields [
"""

TAIL="""]
>>
>>
endobj
trailer

<<
/Root 1 0 R
>>
%%EOF
"""

def output_field( f ):
    return "" + "".join( [ c for c in f ] )

def extract_keys(lines):
    keys = []
    for line in lines:
        if line.startswith('/V'):
            pass
        elif line.startswith('/T'):
            key = line[7:-2]
            key = ''.join(key.split('\x00'))
            keys.append( key )
    return keys

def write_field(out, key, value):
    out.write("<<\n")
    if value:
        out.write("/V (%s)\n" %value)
    else:
        out.write("/V /\n")
    out.write("/T (%s)\n" % output_field(key) )
    out.write(">> \n")

def write_fields(out, fields):
    out.write(HEAD)
    for key in fields:
        value = fields[key]
        write_field(out, key, value)
    out.write(TAIL)

def extract_keys_from_pdf(filename):
    # what about using 'pdftk filename dump_data_fields' and parsing the output ?
    os.system('pdftk %s generate_fdf output /tmp/toto.fdf' % filename)
    lines = file('/tmp/toto.fdf').readlines()
    return extract_keys(lines)


def fill_pdf(infile, outfile, fields):
    write_fields(file('/tmp/toto.fdf', 'w'), fields)
    os.system('pdftk %s fill_form /tmp/toto.fdf output %s flatten' % (infile, outfile))

def testfill_pdf(infile, outfile):
    keys = extract_keys_from_pdf(infile)
    fields = []
    for key in keys:
        fields.append( (key, key, '') )
    fill_pdf(infile, outfile, fields)



4. File inti dari folder report yang namanya telah diimport dari __init__.py yaitu print_pdf.py. Isinya seperti ini :


import os
import pooler
import addons
import tempfile
from pdf_ext import fill_pdf
from report.render import render
from report.interface import report_int

class external_pdf(render):
    def __init__(self, pdf):
        render.__init__(self)
        self.pdf = pdf
        self.output_type='pdf'

    def _render(self):
        return self.pdf


class report_jamsostek(report_int):

    def create(self, cr, uid, ids, datas, context=None):
        pool = pooler.get_pool(cr.dbname)
        
        # Variabel dictionary bernama result, yang keynya diambil dari nama field di file pdf (dilihat dari acrobat reader)
        # Sedangkan valuenya diambil dari field-field pada OpenERP
        result = {
                  'com_name' : datas['form']['data']['name']
        }
        
        # Membuat temporary file
        tmp_file = tempfile.mkstemp(".pdf")[1]
        try:
            # Mencari file pdf berdasarkan path di addons : nama_modul/report/jamsostek.pdf dan mengisinya berdasarkan variabel result yang telah kita tentukan diawal
            fill_pdf(addons.get_module_resource('nama_modul','report','jamsostek.pdf'), tmp_file, result)
            with open(tmp_file, "r") as ofile:
                # Membuat object class baru & Mengambil isi dari temporary file
                self.obj = external_pdf(ofile.read())
        finally:
            # Menghapus temporary file yang telah selesai digunakan
            os.remove(tmp_file)
            
        # Merender file pdf
        self.obj.render()
        
        # Memberikan result pdf file kepada user
        return (self.obj.pdf, 'pdf')
        
report_jamsostek('report.form.jamsostek')


Terakhir adalah menginstall library yang kita butuhkan untuk proses ini yaitu pdftk


sudo apt-get install pdftk

Alhamdulillah akhirnya kita bisa menyelesaikan pembahasan tutorial ini, cara ini juga dapat kita gunakan untuk report pre-printed seperti form faktur pajak, surat jalan, dll. Hanya saja caranya agak berbeda yaitu kita bikin sendiri label inputan dari form kosong.

Kritik dan saran yang membangun sangat penulis harapkan. Selamat mencoba dan semoga bermanfaat …

Advertisements

2 thoughts on “Fill PDF Form

  1. Wah bagus bgt mas modulnya, di linux sudah berhasil
    tapi saya pengen terapkan di windows ternyata error seperti ini
    32
    The process cannot access the file because it is being used by another process

    (, WindowsError(32, ‘The process cannot access the file because it is being used by another process’), )

    walaupun path di windows sudah disesuaikan
    Mohon bantuannya

  2. Hi, first thing first, thank you for your guide on this module.
    May I ask 1 question.
    If in that form have only 20 row for 20 data, but I have 23 data. So how to make another 3 printed to another new form? Any idea? Hmmm…

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