Membuat Custom Report di Odoo 12

Update: Tutorial ini bisa digunakan untuk Odoo 13.

Membuat sebuah custom report di Odoo 12 sedikit berbeda dari Odoo 11. Ada beberapa hal yang harus diubah dari custom report Odoo 11. Seperti contoh sebelumnya custom report Odoo 11, saya masih menggunakan hr_attendance report untuk contoh ini dan akan menampilkan rekap kehadiran karyawan dengan data kehadiran dan ketidakhadiran dari setiap karyawan.

Hasil akhir dari report bisa dilihat seperti dibawah ini.

Hasil akhir custom report Odoo 12

Persiapan awal.

Untuk persiapan awal, anda harus membuat database baru and centang “Load demonstration data”, sehingga ada data awal yang kita bisa gunakan untuk mengetes kode ini nantinya. Lalu instal modul hr_attendance. ini adalah modul bawaan dari Odoo. Dan jangan lupa untuk memastikan bahwa wkhtmltopdf 0.12.1 atau wkhtmltopdf 0.12.5 sudah terinstal.

Setelah menginstal modul hr_attendance, anda bisa melihat data awal seperti dibawah ini.

Data awal hr_attendance

Buat model wizard.

Buat sebuah model wizard yang meng-inherit dari TransientModel.

from odoo import models, fields, api


class AttendanceRecapReportWizard(models.TransientModel):
    _name = 'attendance.recap.report.wizard'

    date_start = fields.Date(string="Start Date", required=True, default=fields.Date.today)
    date_end = fields.Date(string="End Date", required=True, default=fields.Date.today)

    @api.multi
    def get_report(self):
        pass

Buat xml wizard view.

Buat sebuah view untuk menampilkan wizard dari model yang telah kita buat.

<odoo>
    <record model="ir.ui.view" id="attendance_recap_report_wizard">
        <field name="name">HR Attendance Custom Recap Report</field>
        <field name="model">attendance.recap.report.wizard</field>
        <field name="type">form</field>
        <field name="arch" type="xml">
            <form string="Attendance Recap Report">
                <group>
                    <group>
                        <field name="date_start"/>
                    </group>
                    <group>
                        <field name="date_end"/>
                    </group>
                </group>
                <footer>
                    <button name="get_report" string="Get Report" type="object" class="oe_highlight"/>
                    <button string="Cancel" special="cancel"/>
                </footer>
            </form>
        </field>
    </record>

    <act_window id="action_attendance_recap_report_wizard"
                name="Attendance Recap Report"
                res_model="attendance.recap.report.wizard"
                view_mode="form"
                target="new"/>

    <menuitem action="action_attendance_recap_report_wizard"
              id="menu_attendance_report_wizard"
              parent="hr_attendance.menu_hr_attendance_report"/>
</odoo>

Setelah membuat wizard, hasilnya bisa dilihat seperti dibawah ini.

Hasil wizard yang telah dibuat.

Ubah model wizard and buat sebuah abstract model baru.

Ubah method get_report() di model attendance.recap.report.wizard, dan buat sebuah model yang meng-inherit dari AbstractModel, seperti yang bisa dilihat dibawah ini.

# -*- coding: utf-8 -*-

from datetime import datetime

from odoo import models, fields, api
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT


class AttendanceRecapReportWizard(models.TransientModel):
    _name = 'attendance.recap.report.wizard'

    date_start = fields.Date(string="Start Date", required=True, default=fields.Date.today)
    date_end = fields.Date(string="End Date", required=True, default=fields.Date.today)

    @api.multi
    def get_report(self):
        """Call when button 'Get Report' clicked.
        """
        data = {
            'ids': self.ids,
            'model': self._name,
            'form': {
                'date_start': self.date_start,
                'date_end': self.date_end,
            },
        }

        # gunakan `module_name.report_id` sebagai referensi.
        # `report_action()` akan memanggil `_get_report_values()` dan mempassing `data` secara otomatis.
        return self.env.ref('cj_custom_report_v12.recap_report').report_action(self, data=data)


class ReportAttendanceRecap(models.AbstractModel):
    """Abstract Model untuk report template.

    untuk `_name` model gunakan `report.` sebagai prefix lalu tambahkan `module_name.report_name`.
    """

    _name = 'report.cj_custom_report_v12.attendance_recap_report_view'

    @api.model
    def _get_report_values(self, docids, data=None):
        date_start = data['form']['date_start']
        date_end = data['form']['date_end']
        date_start_obj = datetime.strptime(date_start, DATE_FORMAT)
        date_end_obj = datetime.strptime(date_end, DATE_FORMAT)
        date_diff = (date_end_obj - date_start_obj).days + 1

        docs = []
        employees = self.env['hr.employee'].search([], order='name asc')
        for employee in employees:
            presence_count = self.env['hr.attendance'].search_count([
                ('employee_id', '=', employee.id),
                ('check_in', '>=', date_start_obj.strftime(DATETIME_FORMAT)),
                ('check_out', '<=', date_end_obj.strftime(DATETIME_FORMAT)),
            ])

            absence_count = date_diff - presence_count

            docs.append({
                'employee': employee.name,
                'presence': presence_count,
                'absence': absence_count,
            })

        return {
            'doc_ids': data['ids'],
            'doc_model': data['model'],
            'date_start': date_start,
            'date_end': date_end,
            'docs': docs,
        }

Buat xml template report.

Buat sebuah xml untuk template report sesuai dengan kebutuhan.

<odoo>
    <record model="report.paperformat" id="paperformat_attendance_recap_report">
        <field name="name">paperformat.attendance.recap.report</field>
        <field name="default" eval="True"/>
        <field name="format">A4</field>
        <field name="page_width">0</field>
        <field name="page_width">0</field>
        <field name="orientation">Portrait</field>
        <field name="margin_top">30</field>
        <field name="margin_right">5</field>
        <field name="margin_bottom">10</field>
        <field name="margin_left">5</field>
        <field name="header_line" eval="False"/>
        <field name="header_spacing">20</field>
        <field name="dpi">90</field>
    </record>

    <report id="recap_report"
            model="attendance.recap.report.wizard"
            string="Attendance Recap Report"
            report_type="qweb-pdf"
            name="cj_custom_report_v12.attendance_recap_report_view"
            paperformat="paperformat_attendance_recap_report"
            menu="False"/>

    <template id="attendance_recap_report_view">
        <t t-call="web.html_container">
            <div class="header" style="border-bottom: 2px solid black">
                <h3 class="text-center">Attendance Recap Report</h3>
                <h4 class="text-center">
                    <strong>From</strong>:
                    <t t-esc="date_start"/>
                    <strong>To</strong>:
                    <t t-esc="date_end"/>
                </h4>
            </div>
            <div class="article">
                <table class="table table-condensed table-bordered" style="width: 100%">
                    <thead>
                        <th class="text-center" style="width: 70%">Employee</th>
                        <th class="text-center" style="width: 15%">Presence</th>
                        <th class="text-center" style="width: 15%">Absence</th>
                    </thead>
                    <tbody>
                        <t t-foreach="docs" t-as="doc">
                            <tr>
                                <td>
                                    <span t-esc="doc['employee']"/>
                                </td>
                                <td class="text-center">
                                    <span t-esc="doc['presence']"/>
                                </td>
                                <td class="text-center">
                                    <span t-esc="doc['absence']"/>
                                </td>
                            </tr>
                        </t>
                    </tbody>
                </table>
            </div>
            <div class="footer">
                <div class="row text-center" style="border-top: 1px solid black;">
                    <div class="col col-3 offset-9 text-right">
                        <ul class="list-inline mt-2">
                            <li class="list-inline-item">Page:</li>
                            <li class="list-inline-item">
                                <span class="page"/>
                            </li>
                            <li class="list-inline-item">/</li>
                            <li class="list-inline-item">
                                <span class="topage"/>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </t>
    </template>
</odoo>

Jalankan program dan lihat hasilnya.
Silakan cek https://github.com/CakJuice/odoo12-custom-report untuk melihat semua kode, atau anda bisa mengunduh dan meng-instal modul tersebut untuk mencobanya.

Jika anda butuh referensi lain tentang report Odoo 12, silakan cek https://www.odoo.com/documentation/12.0/reference/reports.html.

Terima kasih. Selamat mencoba.

Baca juga:

Comments

1 komentar untuk “Membuat Custom Report di Odoo 12”

  1. Ping-kembali: Cara Menambahkan Image atau Barcode di Report Odoo - Cak Juice

Komentar ditutup.