10 minute read

Banyak programmer pemula belajar membuat aplikasi dari fitur CRUD.

Create data.
Read data.
Update data.
Delete data.

Itu penting. Hampir semua aplikasi bisnis pasti punya CRUD.

Tapi di project nyata, terutama aplikasi enterprise, kebutuhan user biasanya tidak berhenti di sana.

User tidak hanya bertanya:

“Bisa tambah data?”

Mereka juga akan bertanya:

“Sebelum data aktif, bisa approval dulu?”
“Kalau masih draft, jangan masuk proses utama dulu.”
“Bisa lihat siapa yang mengubah data ini?”
“Bisa upload dokumen pendukung?”
“Bisa approve banyak data sekaligus?”
“User cabang A jangan bisa lihat data cabang B.”
“Statusnya kalau sudah rejected bisa di-submit ulang atau tidak?”

Di sinilah perbedaan antara programmer yang hanya bisa membuat CRUD dan programmer yang mulai paham pola fitur enterprise.

Artikel ini membahas 7 pola fitur yang sering muncul di project nyata.


1. Draft dan Submit

Di aplikasi sederhana, setelah user mengisi form lalu klik Save, data langsung dianggap final.

Di aplikasi enterprise, tidak selalu begitu.

Sering kali data perlu disimpan dulu sebagai Draft, lalu baru dikirim ke proses berikutnya dengan tombol Submit.

Contoh:

  • Membuat invoice manual
  • Membuat template collection
  • Membuat pengajuan reimbursement
  • Membuat data kontrak
  • Membuat konfigurasi tarif

Alurnya bisa seperti ini:

Draft -> Submitted / Waiting Approval -> Approved -> Active

Kenapa pola ini penting?

Karena dalam bisnis nyata, user sering belum selesai mengisi data dalam satu waktu. Mereka butuh menyimpan sementara, mengecek ulang, melengkapi attachment, lalu baru submit.

Contoh sederhana status

DRAFT
WAITING_APPROVAL
APPROVED
REJECTED

Saat status masih DRAFT, user boleh mengubah data.

Saat status sudah WAITING_APPROVAL, data biasanya dikunci agar tidak berubah selama proses approval.

Saat APPROVED, data dianggap sah.

Saat REJECTED, sistem bisa mengizinkan user memperbaiki lalu submit ulang, tergantung aturan bisnis.

Hal yang perlu diperhatikan

Jangan hanya membuat tombol Save tanpa memikirkan status data.

Pertanyaan penting yang perlu ditanyakan:

  • Apakah data langsung aktif setelah disimpan?
  • Apakah data perlu dikirim untuk approval?
  • Siapa yang boleh mengubah data saat masih draft?
  • Apakah data rejected boleh diedit lagi?
  • Apakah submit bisa dilakukan jika data belum lengkap?

2. Approval Flow

Approval adalah salah satu fitur paling umum di aplikasi enterprise.

Di project nyata, banyak data tidak boleh langsung aktif hanya karena user menekan tombol Save.

Contoh:

  • Approval pembuatan master data
  • Approval perubahan data pelanggan
  • Approval transaksi pembayaran
  • Approval diskon
  • Approval adjustment billing
  • Approval dokumen kontrak

Approval biasanya melibatkan beberapa role.

Misalnya:

Maker -> Checker -> Approver

Atau:

Staff -> Supervisor -> Manager -> Head Office

Contoh aturan approval

Misalnya ada fitur pengajuan diskon.

Jika diskon <= 5%, approval cukup oleh Supervisor.
Jika diskon > 5%, approval harus sampai Manager.
Jika diskon > 20%, approval harus sampai Direktur.

Dari contoh ini terlihat bahwa approval tidak selalu statis. Kadang approval bergantung pada nominal, cabang, jenis transaksi, atau level risiko.

Struktur data sederhana

Contoh tabel approval bisa memiliki informasi seperti:

approval_id
document_id
document_type
approval_level
approver_role
approver_user_id
status
approved_at
rejected_at
remarks

Hal yang sering dilupakan

Banyak programmer hanya membuat tombol Approve dan Reject.

Padahal dalam enterprise, approval biasanya butuh:

  • Catatan approval atau rejection
  • Validasi apakah user memang berhak approve
  • Urutan approval
  • History approval
  • Notifikasi
  • Lock data saat sedang menunggu approval
  • Kemungkinan resubmit setelah rejected

Approval bukan sekadar tombol. Approval adalah kontrol proses bisnis.


3. History Log

Di aplikasi kecil, perubahan data sering tidak dicatat secara detail.

Di aplikasi enterprise, ini berbahaya.

User, auditor, atau tim support bisa bertanya:

“Siapa yang mengubah data ini?” “Kapan status berubah dari Draft ke Approved?” “Nilai sebelumnya berapa?” “Kenapa data ini rejected?”

Karena itu, history log sangat penting.

Contoh history log

Misalnya ada data kontrak pelanggan.

History log bisa mencatat:

2026-05-01 09:15 - Alam membuat data kontrak dengan status Draft
2026-05-01 10:30 - Alam submit data kontrak untuk approval
2026-05-01 14:20 - Budi reject data kontrak dengan catatan "Nomor dokumen belum sesuai"
2026-05-02 08:10 - Alam update nomor dokumen
2026-05-02 08:15 - Alam submit ulang
2026-05-02 11:00 - Siti approve data kontrak

Dengan history seperti ini, tim support tidak perlu menebak-nebak.

Contoh kolom history

history_id
document_id
document_type
action
old_status
new_status
description
created_by
created_at

Untuk kebutuhan lebih detail, bisa juga menyimpan old_value dan new_value.

Contoh:

{
  "field": "amount",
  "old_value": 1000000,
  "new_value": 1250000
}

Hal yang perlu diperhatikan

Tidak semua perubahan harus dicatat dengan detail yang sama.

Untuk data penting seperti transaksi keuangan, kontrak, atau billing, history harus lebih lengkap.

Untuk data sederhana seperti preferensi tampilan, history mungkin tidak perlu terlalu detail.

Jangan over-engineering, tapi jangan juga mengabaikan audit trail untuk data penting.


4. Attachment

Di project nyata, banyak proses bisnis membutuhkan dokumen pendukung.

Contoh:

  • Bukti pembayaran
  • Surat kontrak
  • Dokumen approval
  • Foto meter
  • Dokumen identitas
  • File Excel hasil upload
  • Berita acara
  • Surat kuasa

Karena itu, fitur attachment sering muncul di aplikasi enterprise.

Contoh kebutuhan attachment

Misalnya user membuat pengajuan adjustment tagihan.

Sistem bisa meminta:

  • Dokumen permohonan
  • Bukti pendukung
  • Catatan internal
  • Lampiran hasil perhitungan

Attachment tidak hanya soal upload file.

Ada beberapa hal yang perlu dipikirkan:

  • Jenis file yang diperbolehkan
  • Ukuran maksimal file
  • Jumlah maksimal file
  • Siapa yang boleh melihat file
  • Siapa yang boleh menghapus file
  • Apakah file boleh diubah setelah submit
  • Apakah file wajib sebelum submit
  • Apakah file perlu virus scanning
  • Apakah file disimpan di database, object storage, atau file server

Contoh struktur attachment

attachment_id
document_id
document_type
file_name
file_path
file_size
mime_type
uploaded_by
uploaded_at
is_deleted

Kolom document_type berguna jika satu tabel attachment dipakai untuk banyak modul.

Contoh:

GAS_DEPOSIT
PAYMENT_ADJUSTMENT
CUSTOMER_CONTRACT
COLLECTION_ACTIVITY

Kesalahan yang sering terjadi

Kesalahan umum adalah menyimpan file tanpa metadata yang cukup.

Akibatnya, saat butuh audit, sistem tidak tahu file ini milik dokumen apa, diupload oleh siapa, dan kapan diupload.


5. Bulk Action

Di aplikasi CRUD dasar, user biasanya memproses data satu per satu.

Tapi di aplikasi enterprise, jumlah data bisa banyak.

Bayangkan user harus approve 500 data satu per satu. Itu tidak efisien.

Karena itu, sering muncul fitur bulk action.

Contoh bulk action:

  • Bulk approve
  • Bulk reject
  • Bulk delete
  • Bulk submit
  • Bulk assign
  • Bulk download
  • Bulk upload
  • Bulk update status

Contoh alur bulk approval

User memilih beberapa data
User klik Bulk Approve
Sistem validasi semua data
Jika valid, sistem approve data
Jika sebagian gagal, sistem tampilkan data mana yang gagal dan alasannya

Hal penting dalam bulk action

Bulk action terlihat sederhana di UI, tapi cukup tricky di backend.

Misalnya user memilih 100 data untuk approval.

Beberapa kemungkinan:

  • 90 data valid
  • 10 data sudah pernah di-approve
  • 5 data bukan wewenang user
  • 3 data sedang diproses user lain
  • 2 data sudah berubah status sejak halaman dibuka

Sistem harus jelas menangani ini.

Ada dua pendekatan umum:

Pendekatan 1: All or Nothing

Jika ada satu data gagal, semua proses dibatalkan.

Kelebihan:

  • Data lebih konsisten
  • Mudah dipahami

Kekurangan:

  • User harus memperbaiki semua error dulu
  • Kurang fleksibel untuk data besar

Pendekatan 2: Partial Success

Data yang valid tetap diproses, data yang gagal ditampilkan alasannya.

Kelebihan:

  • Lebih praktis untuk user
  • Cocok untuk volume data besar

Kekurangan:

  • Perlu reporting hasil proses yang jelas
  • Backend lebih kompleks

Contoh hasil bulk action

Total selected: 100
Success: 92
Failed: 8

Detail error:

Data INV-001 gagal: status sudah Approved
Data INV-009 gagal: user tidak memiliki akses approval
Data INV-017 gagal: data sedang diproses

Jangan membuat bulk action tanpa hasil proses yang jelas. User perlu tahu mana yang sukses dan mana yang gagal.


6. Role Access

Di aplikasi enterprise, tidak semua user boleh melakukan semua hal.

Role access adalah fitur yang mengatur siapa boleh melihat, membuat, mengubah, menghapus, submit, approve, atau export data.

Contoh role:

Admin
Maker
Checker
Approver
Viewer
Finance
Supervisor
Manager

Tapi dalam project nyata, role saja sering belum cukup.

Kadang akses juga bergantung pada area, cabang, divisi, atau jenis data.

Contoh:

User cabang Jakarta hanya boleh melihat data Jakarta.
User cabang Bandung hanya boleh melihat data Bandung.
User pusat boleh melihat semua data.

Ini disebut juga data scope atau row-level access.

Contoh permission

COLLECTION_ACTIVITY_CREATE
COLLECTION_ACTIVITY_UPDATE
COLLECTION_ACTIVITY_SUBMIT
COLLECTION_ACTIVITY_APPROVE
COLLECTION_ACTIVITY_REJECT
COLLECTION_ACTIVITY_VIEW
COLLECTION_ACTIVITY_EXPORT

Dengan permission seperti ini, sistem lebih fleksibel daripada hanya menggunakan role sederhana.

Role bisa berisi kumpulan permission.

Contoh:

Role: Collection Maker
Permissions:
- COLLECTION_ACTIVITY_CREATE
- COLLECTION_ACTIVITY_UPDATE
- COLLECTION_ACTIVITY_SUBMIT
- COLLECTION_ACTIVITY_VIEW
Role: Collection Approver
Permissions:
- COLLECTION_ACTIVITY_VIEW
- COLLECTION_ACTIVITY_APPROVE
- COLLECTION_ACTIVITY_REJECT

Hal yang sering dilupakan

Banyak programmer hanya menyembunyikan tombol di frontend.

Misalnya tombol Approve disembunyikan dari user yang tidak berhak.

Itu bagus, tapi belum cukup.

Validasi akses tetap harus dilakukan di backend.

Kenapa?

Karena user bisa saja memanggil API langsung menggunakan Postman, browser dev tools, atau script.

Jadi pola yang benar:

Frontend: menyembunyikan tombol agar UI rapi
Backend: tetap validasi permission agar aman

7. Status Lifecycle

Status lifecycle adalah aturan perubahan status dari satu kondisi ke kondisi lain.

Ini salah satu bagian paling penting dalam aplikasi enterprise.

Contoh status sederhana:

Draft -> Waiting Approval -> Approved -> Active

Tapi di project nyata, status bisa lebih kompleks.

Contoh:

Draft
Waiting Approval
Approved
Rejected
Active
Inactive
Expired
Cancelled

Tidak semua status boleh berpindah bebas.

Misalnya:

Draft -> Waiting Approval
Waiting Approval -> Approved
Waiting Approval -> Rejected
Rejected -> Draft
Approved -> Active
Active -> Inactive
Active -> Expired

Tapi mungkin tidak boleh:

Approved -> Draft
Expired -> Active
Cancelled -> Approved

Kenapa status lifecycle penting?

Karena status menentukan perilaku sistem.

Contoh:

Status Boleh Edit? Boleh Submit? Boleh Approve? Boleh Delete?
Draft Ya Ya Tidak Ya
Waiting Approval Tidak Tidak Ya Tidak
Approved Tidak Tidak Tidak Tidak
Rejected Ya Ya Tidak Ya
Active Terbatas Tidak Tidak Tidak
Expired Tidak Tidak Tidak Tidak

Tanpa status lifecycle yang jelas, aplikasi akan mudah kacau.

User bisa melakukan aksi yang tidak seharusnya. Data bisa berubah di waktu yang salah. Tim QA juga akan kesulitan membuat test case.

Contoh validasi status di backend

Pseudo-code sederhana:

if current_status == "DRAFT" and action == "SUBMIT":
    new_status = "WAITING_APPROVAL"

else if current_status == "WAITING_APPROVAL" and action == "APPROVE":
    new_status = "APPROVED"

else if current_status == "WAITING_APPROVAL" and action == "REJECT":
    new_status = "REJECTED"

else:
    throw Error("Action is not allowed for current status")

Validasi seperti ini sebaiknya tidak hanya ditaruh di frontend.

Backend harus menjadi penjaga utama aturan status.


Contoh Gabungan di Satu Fitur

Agar lebih mudah dibayangkan, kita ambil contoh fitur pengajuan adjustment tagihan.

User membuat pengajuan.

Status awal:

DRAFT

User melengkapi data dan upload attachment.

Lalu klik Submit.

Status berubah menjadi:

WAITING_APPROVAL

Supervisor membuka daftar approval.

Supervisor bisa approve atau reject.

Jika reject, sistem meminta catatan rejection.

Status berubah menjadi:

REJECTED

User memperbaiki data, lalu submit ulang.

Jika approved, status berubah menjadi:

APPROVED

Setelah approved, data tidak boleh diedit sembarangan.

Selama proses itu, sistem mencatat history:

Created as Draft
Attachment uploaded
Submitted for approval
Rejected by Supervisor
Updated by Maker
Resubmitted
Approved by Supervisor

Jika ada 100 pengajuan, approver bisa memakai bulk approval.

Tapi sistem tetap harus memvalidasi:

  • Apakah user punya akses approve?
  • Apakah status data memang Waiting Approval?
  • Apakah data masih aktif?
  • Apakah attachment wajib sudah tersedia?
  • Apakah data sedang diproses user lain?

Dari contoh ini terlihat bahwa fitur enterprise bukan hanya CRUD.

CRUD hanya pondasinya.

Yang membuat sistem siap dipakai di perusahaan adalah aturan proses bisnis di atasnya.


Checklist untuk Programmer

Saat membuat fitur baru, jangan langsung hanya berpikir tabel dan form CRUD.

Coba tanyakan beberapa hal berikut:

Data dan Status

  • Apa status awal data?
  • Kapan data dianggap final?
  • Apakah data bisa diedit setelah submit?
  • Apakah data bisa dihapus setelah approved?
  • Apakah data rejected boleh diperbaiki?

Approval

  • Apakah fitur ini butuh approval?
  • Siapa yang approve?
  • Apakah approval satu level atau multi-level?
  • Apakah rejection wajib memakai catatan?
  • Apakah data dikunci saat approval?

History

  • Perubahan apa saja yang perlu dicatat?
  • Siapa yang melakukan perubahan?
  • Apakah perlu menyimpan nilai sebelum dan sesudah?
  • Apakah history perlu ditampilkan ke user?

Attachment

  • Apakah butuh dokumen pendukung?
  • File apa saja yang diperbolehkan?
  • Apakah attachment wajib sebelum submit?
  • Apakah file boleh dihapus setelah submit?

Bulk Action

  • Apakah user akan memproses banyak data?
  • Apakah bulk action harus all-or-nothing?
  • Apakah boleh partial success?
  • Bagaimana menampilkan data yang gagal diproses?

Role Access

  • Siapa yang boleh create?
  • Siapa yang boleh update?
  • Siapa yang boleh approve?
  • Siapa yang boleh export?
  • Apakah akses dibatasi berdasarkan cabang, area, atau divisi?

Penutup

Belajar CRUD itu penting, tapi jangan berhenti di CRUD.

Di project nyata, terutama aplikasi enterprise, programmer perlu memahami pola fitur seperti:

  1. Draft dan submit
  2. Approval flow
  3. History log
  4. Attachment
  5. Bulk action
  6. Role access
  7. Status lifecycle

Pola-pola ini sering muncul di banyak sistem bisnis, baik itu billing system, ERP, CRM, procurement, HRIS, finance system, maupun aplikasi internal perusahaan.

Kalau kamu sudah mulai terbiasa memikirkan hal-hal ini, cara kamu mendesain fitur akan naik level.

Kamu tidak hanya bertanya:

“Tabelnya apa saja?”

Tapi mulai bertanya:

“Proses bisnisnya bagaimana?” “Statusnya berubah dari mana ke mana?” “Siapa yang boleh melakukan aksi ini?” “Apa yang terjadi kalau data sudah approved?” “Bagaimana kalau sebagian data gagal diproses?”

Itulah pola pikir yang dibutuhkan untuk membangun aplikasi enterprise yang lebih siap dipakai di dunia nyata.


Comments