Lembur, Reimburse & Cuti: HR Requests
Pengajuan lembur, biaya perjalanan, justifikasi keterlambatan, kunjungan klien. Approval flow ke admin tim, OCR struk otomatis dengan AI, integrasi ke Payroll.
- 1
Apa itu HR Requests
Plugin HR Requests handle 4 jenis pengajuan karyawan yang berdampak ke gaji/operasional:
- Lembur (
overtime), kerja di luar jam shift, dengan estimasi jam + amount kompensasi - Justifikasi Keterlambatan (
lateness_excuse), pembelaan telat dengan alasan + bukti opsional - Reimbursement (
reimbursement), claim biaya kerja (transport, makan klien, ATK) dengan struk + OCR auto-extract - Kunjungan Klien (
visit), visit log untuk staff lapangan, dengan target lokasi + durasi
Setiap pengajuan butuh approval dari admin tim (role
admin_teamdi tim staff). Sekali approved, data flow ke Payroll otomatis tiap akhir bulan.Aktifkan plugin di Pengaturan → Plugin → Lembur & HR. Plugin name di backend masih
overtime(legacy, dipertahankan untuk backward compat URL/lembur).- Plugin Pro+, Free plan gak ada akses pengajuan
- OCR struk butuh AI quota workspace, count sebagai 1 AI call per scan
- Lembur (
- 2
Cara ajukan lembur
Staff selesai project late night, butuh kompensasi:
Buka /lembur → + Pengajuan Baru → Lembur:
- Tim (dropdown, tim yang kamu member-nya)
- Tanggal & jam mulai (mis. 21 Mei 17:30)
- Tanggal & jam selesai (mis. 21 Mei 22:00)
- Total jam lembur auto-calc dari rentang (4.5 jam)
- Tarif per jam (default ambil dari salary profile / 173 jam standar bulanan; bisa override dengan persetujuan)
- Total amount auto = jam × tarif (mis. 4.5 × Rp 50.000 = Rp 225.000)
- Alasan / deskripsi tugas (teks, wajib, mis. "Lembur perbaikan bug kritis di sistem pembayaran klien")
Klik Submit. Status Pending. Notif terkirim ke semua admin tim, push notif + notif dalam aplikasi + email (kalau diaktifkan).
Pelajaran penting: lembur tanpa nominal = sekadar catatan, kadang admin minta staff mencatat lembur untuk tracking jam, tanpa kompensasi finansial. Set nominal = 0.
Pengajuan lembur retroaktif diizinkan, tapi audit log catat lag, admin bisa policy "max H+3 dari kejadian". Soft policy, gak hard-block. - 3
Cara ajukan reimbursement (dengan OCR AI)
Staff naik Grab ke klien meeting, ada biaya bensin perjalanan dinas, dll:
Buka /lembur → + Pengajuan → Reimbursement:
- Tim
- Tanggal pengeluaran
- Kategori dropdown: Transport, Makan Klien, ATK, Komunikasi, Lain-lain
- Amount dalam rupiah
- Deskripsi (mis. "Grab ke klien Acme di Sudirman")
- Upload struk (foto JPG/PNG/HEIC/WEBP, max 8MB)
Trik AI: drag-drop struk dulu sebelum isi field. AI auto-OCR dalam ~3 detik dan auto-fill:
- Nama merchant (mis. "GRAB INDONESIA")
- Tanggal struk
- Amount (deteksi total final, bukan subtotal)
- Suggested kategori (Transport karena merchant Grab)
- Tax detected (kalau ada PPN line item)
Staff cuma review + edit kalau ada salah → submit. Lebih cepat 5x dari isi manual.
OCR limits:
- Format: gambar saja (PDF struk = upload manual)
- Max 8MB file size
- Kuota: count sebagai 1 AI call workspace per scan, di-track di audit
- Fallback: kalau AI gagal parse (struk burik / non-Indonesia / tulisan tangan), error message → staff isi manual
- Struk yang clear dan diambil dari atas (top-down view, gak miring) akurasi >95%. Struk miring/lipat akurasi turun ke 70%.
- 4
Cara ajukan justifikasi keterlambatan
Staff telat 30 menit hari Senin karena macet KRL gangguan sinyal. Tanpa justifikasi, status
latedi rekap → potong gaji (kalau tarif denda aktif).Buka /lembur → + Pengajuan → Justifikasi Keterlambatan:
- Tim
- Tanggal kejadian
- Alasan (text, mis. "KRL Bogor-Jakarta gangguan sinyal Stasiun Manggarai, terlambat 35 menit")
- Bukti (foto opsional, screenshot pengumuman KRL, tilang, hospital receipt, dll)
Amount = 0 (justifikasi tidak ada kompensasi, cuma exclude dari denda).
Admin tim review → kalau approved:
- Status pengajuan
approved - Record attendance hari itu masih
late(tidak modify), tapi Payroll skip record ini saat hitung potongan denda - Net effect: gaji bulan itu tidak kepotong untuk telat tanggal itu
Kalau rejected (admin gak terima alasan): potongan tetap berlaku.
Plugin Absensi harus aktif buat fitur ini ada efek finansial. Kalau Absensi off, justifikasi cuma jadi catatan tanpa pengaruh slip. - 5
Cara ajukan visit / kunjungan klien
Staff sales sering visit ke klien, perlu log untuk reporting + reimburse transport:
Buka /lembur → + Pengajuan → Visit:
- Tim (sales / BD / account management)
- Tanggal & jam mulai visit
- Tanggal & jam selesai visit (optional, kosong = ongoing, isi saat balik kantor)
- Nama klien / lokasi (mis. "PT Maju Mundur, Office Sudirman")
- Tujuan visit (mis. "Demo product feature X")
- Amount opsional (kalau request reimburse transport sekaligus, atau bikin pengajuan terpisah)
Visit di-track terpisah dari Absensi mode
visit(clock-in lapangan). Beda:- Absensi
visitmode → clock-in/out langsung dari lapangan + GPS recorded. Statusremote. Real-time. - HR Request
visit→ submit setelah kejadian (atau saat berangkat) untuk approval. Tidak butuh GPS.
Gunakan sesuai workflow: kalau ada perlu approval atasan dulu → HR Request. Kalau cuma log presence → Absensi visit mode.
- Field staff bisa kombinasikan: Absensi visit mode untuk daily clock + HR Request visit untuk weekly summary
- 6
Approval flow (sisi admin)
admin_teamdi setiap tim handle approval. Buka /lembur → tab "Perlu Review" → list pending dari semua tim yang admin tim-nya kamu.Per pengajuan kelihatan:
- Type (badge warna)
- Requester (foto + nama)
- Tim
- Tanggal kejadian
- Amount (kalau ada)
- Description
- Lampiran (struk foto / bukti dokumen)
Aksi per pengajuan:
- ✅ Approve, kasih note opsional (mis. "OK lembur, next time ajukan H-1 ya"). Status
approved. Notif ke requester (push + in-app). - ❌ Reject, note wajib (mis. "Reimburse makan pribadi tidak qualified untuk dinas, hanya entertain klien"). Status
rejected. Notif ke requester dengan alasan. - 🔄 Request More Info (Phase 2, coming soon), bouncing back ke requester dengan note, tanpa final decision.
Bulk actions untuk reviewer dengan banyak antrian: select multiple → "Approve all" / "Reject all dengan template note". Best practice: gak abuse, tiap pengajuan deserve individual review.
Filter: type, requester, tim, rentang tanggal, range amount. Useful untuk monthly review.
Admin tim BUKAN admin workspace. Admin workspace bisa override approval (Phase 2, feature toggle), tapi default cuma admin tim yang approve. - 7
Cancel pengajuan pending (sisi requester)
Staff salah submit (typo amount, tanggal salah), selama status masih
pending, bisa cancel sendiri./lembur → daftar pengajuan saya → klik pengajuan → tombol "Batalkan":
- Status
pending→cancelled - Notifikasi ke admin tim "Pengajuan dibatalkan oleh requester"
- Audit log: cancel timestamp + requester ID
Setelah cancel, gak bisa di-undo. Submit lagi pengajuan baru kalau perlu.
Catatan:
approved/rejectedgak bisa di-cancel. Buat ralat post-approval, admin workspace harus manual edit di Payroll run (audit log). - Status
- 8
Lihat history pengajuan saya
Staff buka /lembur → tab "Punya saya" → list semua pengajuan personal historical.
Filter: status (pending / approved / rejected / cancelled), type, periode.
Stats personal di header:
- Total pengajuan bulan ini
- Approval rate (% approved dari total non-pending)
- Total amount approved (rupiah)
- Pending count (yang masih nunggu admin)
Useful buat self-monitor: kalau approval rate < 50%, mungkin perlu re-think cara submit (alasan lebih jelas, bukti lebih lengkap).
- 9
Rekap admin (Fase 5: summary endpoint)
Workspace admin / HR Manager butuh aggregat untuk reporting. /lembur/admin → tab "Rekap":
Pilih rentang periode + tim (opsional) + user (opsional). Output:
Lembur:
- Total pengajuan approved
- Total jam lembur
- Total Rp kompensasi lembur
Keterlambatan:
- Total incident justifikasi (insiden, bukan staff, 1 staff bisa multiple)
Reimbursement:
- Total Rp di-approve
- Breakdown per kategori (Transport: 15jt, Makan Klien: 5jt, ATK: 2jt, ...)
Kunjungan:
- Total visit count
- Total durasi (menit), kalau visit punya rentang from-to
Export CSV/Excel untuk integrasi dashboard external atau report bulanan ke direktur.
- Limit query summary: 5000 record max, kalau workspace besar (>5000 pengajuan/bulan), pakai filter periode lebih kecil
- Data summary cuma approved, pending/rejected/cancelled di-skip
- 10
Integrasi ke Payroll otomatis
Setiap akhir bulan, plugin Payroll auto-include data HR Requests approved ke slip gaji:
Lembur approved dalam periode →
- Ditambahkan ke komponen lembur di slip gaji
- Taxable (masuk basis PPh21)
Reimbursement approved dalam periode →
- Ditambahkan ke komponen reimbursement di slip gaji
- Non-taxable default (reimburse = ganti uang yang dikeluarin staff, bukan additional income)
- Beberapa kategori tertentu (mis. makan teratur, allowance regular) bisa taxable, atur di komponen tetap profile, bukan di reimbursement individual
Justifikasi keterlambatan approved →
- Saat menghitung potongan keterlambatan, catatan absensi di-skip kalau ada justifikasi approved untuk hari yang sama
- Net effect: gaji tidak dipotong
Visit → tidak ada efek finansial otomatis. Cuma logging. Untuk reimburse transport visit, submit terpisah sebagai reimbursement.
Workflow ideal:
- Tanggal 25 setiap bulan: HR remind staff submit pending pengajuan (notifikasi otomatis dari sistem)
- Tanggal 26-28: admin tim batch approve
- Tanggal 29: HR finalisasi attendance, justifikasi sudah selesai semua approval
- Tanggal 30: generate payroll run, auto-include semua approved entries
Pengajuan submitted setelah tanggal generate run tidak ke-include, harus tunggu run bulan berikutnya, atau admin manual edit slip historical (audit log). - 11
Notifikasi push & in-app
Komunikasi real-time penting untuk approval flow gak stuck:
Saat submit: → admin tim dapet 3-channel notif:
- Push (PWA mobile): "Pengajuan baru, [Nama Staff] mengajukan lembur"
- In-app: red badge di sidebar /lembur, list di Notification Center
- Email (kalau staff enable): summary harian (daily digest) bukan instant, anti-spam
Saat approved: → requester dapet:
- Push: "Pengajuan disetujui ✅, Lembur 21 Mei"
- In-app: notification list dengan link ke detail pengajuan
- Email opsional
Saat rejected: → requester dapet:
- Push: "Pengajuan ditolak, Lihat alasannya"
- Note rejection ditampilkan di detail pengajuan + email body
Customize per-user: Pengaturan → Notifikasi → HR Requests → toggle channel + jenis event yang di-receive. Default: semua ON untuk admin tim, daily-only untuk staff.
- 12
Permission matrix + access scope
Plugin enforce role-based access ketat untuk legal/HR sensitive:
| Role | List own | List team | List all | Submit | Approve | Edit pasca-approve |
|------|----------|-----------|----------|--------|---------|---------------------|
|member| ✅ | ❌ | ❌ | ✅ | ❌ | ❌ (cancel own pending only) |
|admin_team(tim X) | ✅ | ✅ (tim X) | ❌ | ✅ | ✅ (tim X) | ❌ |
|admin_workspace| ✅ | ✅ (semua tim) | ✅ | ✅ | ✅ (semua tim) | ✅ (audit log) |
|owner| sama dengan admin_workspace |Query scope di-enforce di backend via
getVisibleUserIds()helper, bahkan kalau frontend bypass filter URL, data tetap difilter.Edge case: admin tim sekaligus member tim lain. Dia bisa approve di tim yang dia admin-nya, tapi cuma submit + view personal di tim lain (member role di sana).
Sensitive HR data, di-track ke audit log immutable. Owner workspace bisa lihat semua, tapi admin tim cuma tim mereka. Inspection compliance straightforward. - 13
Plan gating + AI quota
Plugin HR Requests Pro+ (per workspace plan):
- Free: gak ada akses
- Pro: full plugin (submit, approve, integrate Payroll), tapi OCR struk = AI feature, jadi consume AI quota (default 100/bulan Pro)
- Business: + bulk approve, + custom approval workflow per-tim, + AI quota lebih besar (500/bulan)
- Enterprise: + multi-level approval (manager → director → CEO), + integration API ke ERP eksternal
OCR struk specifically:
- 1 scan = 1 AI call
- Pemakaian quota AI tercatat per workspace
- Reset awal bulan otomatis
- Kalau quota habis: muncul pesan "Kuota AI workspace habis" → staff isi manual reimburse field
Upgrade kalau quota sering habis: Pengaturan → Billing.
Plan gate enforced di middleware, bypass via API direct ke endpoint juga di-reject 403. - 14
Cuti tahunan / sakit / izin (link ke tutorial Cuti)
Selain 4 type pengajuan di atas, HR Requests sekarang juga handle 4 type cuti / leave:
- Annual leave (
annual_leave), cuti tahunan, deduct kuota 12 hari/tahun default (UU Cipta Kerja Pasal 79) - Sick leave (
sick_leave), sakit, surat dokter wajib > 2 hari - Permission leave (
permission_leave), izin pribadi (urusan keluarga, dll), umumnya unpaid - Maternity leave (
maternity_leave), cuti melahirkan 3 bulan UU Cipta Kerja, tidak deduct annual quota
Flow sama dengan pengajuan lain (submit → approve → notif), tapi otomatis:
- Validasi kuota saat submit (cuti tahunan ditolak kalau sisa < hari yang diminta)
- Validasi H-N advance notice (default H-3 untuk cuti tahunan)
- Hitung working days otomatis (skip weekend + hari libur)
- Auto-deduct balance saat approve
- Auto-refund balance kalau requester cancel sebelum tanggal mulai
Lihat tutorial dedicated Cuti & Leave Management untuk detail kuota policy, carry-over, dan integrasi ke Payroll.
- Annual leave (
- 15
Troubleshooting HR Requests
Masalah umum + fix:
"Kamu bukan anggota tim ini" saat submit:
→ User tidak terdaftar di tim yang dipilih. Cek /teams → tim X → Anggota. Admin tambah user."Tidak berhak approve pengajuan ini":
→ User bukan admin tim untuk tim pengajuan. Cuma admin tim yang sama dengan pengajuan yang bisa approve.OCR struk hasil salah (amount/tanggal/merchant):
→ Struk burik/miring/non-standar (tulisan tangan, ukuran kecil). Edit manual field, simpan. AI improve over time dengan training data."AI OCR reimbursement gagal":
→ Layanan AI sedang bermasalah atau timeout. Coba ulang 30 detik kemudian. Kalau persistent, fallback ke isi manual."Kuota AI workspace habis":
→ Workspace AI quota bulan habis. Upgrade plan atau tunggu reset awal bulan. Atau isi reimburse manual tanpa OCR.Pengajuan approved tapi gak masuk Payroll bulan ini:
→ Cek tanggal mulai pengajuan, harus dalam rentang periode payroll run (mis. run Mei = tanggal antara 1 Mei dan 31 Mei).Notif push gak masuk:
→ PWA gak ter-install / notif permission gak granted. Pengaturan → Notifikasi cek status. Re-grant kalau perlu."Pengajuan sudah diproses" saat approve/reject:
→ Pengajuan udah di-approve/reject sebelumnya (race condition antar admin tim). Refresh untuk lihat status terbaru.Staff lapor "pengajuan saya nggak nongol":
→ Cek filter view, mungkin tab "Punya saya" vs "Tim", pengajuan personal di tab "Punya saya". Atau status filter saat ini exclude status pengajuan (mis. filter "approved" tapi pengajuan masih pending).Masih stuck? /support/new dengan: pengajuan ID, screenshot, expected vs actual.