Membuat custom report di Odoo 11 sangat berbeda dengan membuat custom report di Odoo 10. Itu dikarenakan di Odoo 11 tidak mempunyai modul report
seperti yang ada pada Odoo 10. Dan diperparah lagi dengan dokumentasi yang salah pada website Odoo, seperti yang bisa dilihat di dokumentasi Odoo ini.
Untuk itu, kali ini saya akan membuat tutorial custom report di Odoo 11, sama seperti dengan konsep yang ada pada tutorial custom report sebelumnya di Odoo 10.
Di tutorial ini saya tetap akan menampilkan rekap kehadiran karyawan, dan menampilkan data kehadiran dan ketidakhadiran tiap karyawan.
Hasil akhir dari report adalah seperti ini.
Seperti sebelumnya, sebelum memulai silakan membuat database baru dengan mencentang “Load demonstration data” agar ada data awal yang bisa kita gunakan untuk mengetes program. Lalu install modul hr_attendance
. Modul tersebut adalah modul presensi bawaan dari Odoo. Dan jangan lupa memastikan bahwa wkhtmltopdf
telah diinstall. Di report ini saya menggunakan wkhtmltopdf
versi 0.12.1.
Setelah menginstall modul hr.attendance
bisa dilihat data kehadiran dengan demo data sebagai berikut.
Buat sebuah model wizard.
Buat sebuah model wizard yang meng-inherit 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 sebuah view xml untuk model wizard yang telah dibuat.
Buat sebuah view untuk menampilkan wizard berdasarkan model wizard diatas.
<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 maka hasil tampilannya adalah seperti gambar dibawah ini.
Ubah class AttendanceRecapReportWizard.
Ubah method get_report()
pada model attendance.recap.report.wizard
, dan buat sebuah model yang meng-inherit AbstractModel
untuk membuat custom report. Hasil akhirnya bisa dilihat pada kode di bawah ini.
from datetime import datetime, timedelta
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,
},
}
# use `module_name.report_id` as reference.
# `report_action()` will call `get_report_values()` and pass `data` automatically.
return self.env.ref('cj_custom_report.recap_report').report_action(self, data=data)
class ReportAttendanceRecap(models.AbstractModel):
"""Abstract Model for report template.
for `_name` model, please use `report.` as prefix then add `module_name.report_name`.
"""
_name = 'report.cj_custom_report.attendance_recap_report_view'
@api.model
def get_report_values(self, docids, data=None):
date_start = datetime.strptime(data['form']['date_start'], DATE_FORMAT)
date_end = datetime.strptime(data['form']['date_end'], DATE_FORMAT) + timedelta(days=1)
date_diff = (date_end - date_start).days
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.strftime(DATETIME_FORMAT)),
('check_out', '<', date_end.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.strftime(DATE_FORMAT),
'date_end': (date_end - timedelta(days=1)).strftime(DATE_FORMAT),
'docs': docs,
}
Buat file xml template report.
Setelah itu buat file 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.attendance_recap_report_view"
paperformat="paperformat_attendance_recap_report"
menu="False"/>
<template id="attendance_recap_report_view">
<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-xs-3 col-xs-offset-9 text-right">
<ul class="list-inline" style="margin-top:10px;">
<li>Page:</li>
<li>
<span class="page"/>
</li>
<li>/</li>
<li>
<span class="topage"/>
</li>
</ul>
</div>
</div>
</div>
</template>
</odoo>
Sekian tutorial kali ini, silakan cek repository untuk melihat kodenya secara utuh, atau bisa langsung install modul tersebut untuk mencoba.
Selamat mencoba, semoga bermanfaat.
Baca juga:
Comments
Ping-kembali: Membuat Odoo attachment otomatis di Odoo 10 dan 11 - Cak Juice
Ping-kembali: Membuat Custom Report di Odoo 12 - Cak Juice
Ping-kembali: Cara Menambahkan Image atau Barcode di Report Odoo - Cak Juice