Tutorial 23 Aug 2026 2 Kali Dibaca

Cara Membuat Sistem Approval Bertingkat di Laravel

Gugun Nurdiansyah
Penulis
Cara Membuat Sistem Approval Bertingkat di Laravel

Apa Itu Approval Bertingkat?

Approval bertingkat adalah proses persetujuan yang dilakukan berdasarkan urutan tertentu.

Contohnya:

Pengajuan
↓
Supervisor
↓
Manager
↓
Direktur
↓
Disetujui

Jika salah satu level menolak:

Pengajuan
↓
Supervisor
↓
Ditolak

Sistem seperti ini membantu perusahaan membuat proses persetujuan lebih terstruktur dan mudah dilacak.

Contoh Status Approval

Pengajuan dapat memiliki status:

draft
pending
approved
rejected
cancelled

Sedangkan setiap level approval dapat memiliki:

pending
approved
rejected

1. Membuat Tabel Pengajuan

Contoh migration:

Schema::create('requests', function (Blueprint $table) {
    $table->id();

    $table->foreignId('user_id')
        ->constrained();

    $table->string('title');
    $table->text('description')->nullable();

    $table->string('status')
        ->default('draft');

    $table->timestamps();
});

Kemudian:

php artisan migrate

2. Membuat Tabel Approval

Buat tabel khusus untuk menyimpan setiap tahapan approval:

Schema::create('approvals', function (Blueprint $table) {
    $table->id();

    $table->foreignId('request_id')
        ->constrained();

    $table->foreignId('approver_id')
        ->constrained('users');

    $table->unsignedInteger('level');

    $table->string('status')
        ->default('pending');

    $table->text('notes')->nullable();

    $table->timestamp('approved_at')
        ->nullable();

    $table->timestamps();
});

Strukturnya menjadi:

Request
  ↓
Approval Level 1
  ↓
Approval Level 2
  ↓
Approval Level 3

3. Membuat Model

Model Request:

class RequestModel extends Model
{
    protected $fillable = [
        'user_id',
        'title',
        'description',
        'status',
    ];

    public function approvals()
    {
        return $this->hasMany(Approval::class);
    }
}

Model Approval:

class Approval extends Model
{
    protected $fillable = [
        'request_id',
        'approver_id',
        'level',
        'status',
        'notes',
        'approved_at',
    ];

    public function approver()
    {
        return $this->belongsTo(
            User::class,
            'approver_id'
        );
    }
}

4. Membuat Approval Saat Pengajuan Dibuat

Misalnya terdapat tiga level:

Level 1 → Supervisor
Level 2 → Manager
Level 3 → Direktur

Ketika pengajuan dibuat:

$requestModel = RequestModel::create([
    'user_id' => auth()->id(),
    'title' => $request->title,
    'description' => $request->description,
    'status' => 'pending',
]);

Kemudian buat approval:

Approval::create([
    'request_id' => $requestModel->id,
    'approver_id' => $supervisorId,
    'level' => 1,
]);

Approval::create([
    'request_id' => $requestModel->id,
    'approver_id' => $managerId,
    'level' => 2,
]);

Approval::create([
    'request_id' => $requestModel->id,
    'approver_id' => $directorId,
    'level' => 3,
]);

5. Hanya Level Aktif yang Bisa Approve

Misalnya pengajuan masih berada di level 1.

Supervisor → Bisa approve
Manager    → Belum bisa
Direktur   → Belum bisa

Cek level aktif:

$currentLevel = $requestModel
    ->approvals()
    ->where('status', 'pending')
    ->min('level');

Kemudian pastikan user adalah approver pada level tersebut.

$approval = $requestModel
    ->approvals()
    ->where('level', $currentLevel)
    ->where('approver_id', auth()->id())
    ->where('status', 'pending')
    ->first();

Jika tidak ditemukan:

abort(403, 'Anda belum dapat melakukan approval.');

6. Proses Approve

Contohnya:

DB::transaction(function () use ($approval) {

    $approval->update([
        'status' => 'approved',
        'approved_at' => now(),
    ]);

    $nextLevel = Approval::where(
        'request_id',
        $approval->request_id
    )
    ->where('status', 'pending')
    ->min('level');

    if (!$nextLevel) {
        RequestModel::where(
            'id',
            $approval->request_id
        )->update([
            'status' => 'approved',
        ]);
    }
});

Jika masih ada level berikutnya, pengajuan tetap menunggu approval berikutnya.

7. Proses Reject

Jika approver menolak:

DB::transaction(function () use (
    $approval,
    $request
) {

    $approval->update([
        'status' => 'rejected',
        'notes' => $request->notes,
    ]);

    RequestModel::where(
        'id',
        $approval->request_id
    )->update([
        'status' => 'rejected',
    ]);
});

Alurnya:

Level 1
↓
Approved
↓
Level 2
↓
Rejected
↓
Pengajuan Rejected

8. Tambahkan Catatan Approval

Approver sebaiknya dapat memberikan alasan.

Contohnya:

Status : Rejected

Catatan:
Dokumen pendukung belum lengkap.

Field:

$table->text('notes')->nullable();

Dengan begitu, pengguna mengetahui alasan pengajuan ditolak.

9. Membuat Tampilan Approval

Contoh sederhana:

Pengajuan Pembelian Laptop

✓ Supervisor
  Disetujui
  23 Agustus 2026

● Manager
  Menunggu Approval

○ Direktur
  Menunggu Approval

Tampilan seperti timeline akan memudahkan pengguna memahami posisi pengajuan.

10. Tambahkan Role dan Permission

Approval sebaiknya tidak hanya berdasarkan user ID.

Contohnya:

Supervisor
Manager
Direktur

Gunakan role atau permission untuk menentukan siapa yang dapat melakukan approval.

Contoh:

approval.purchase.supervisor
approval.purchase.manager
approval.purchase.director

Hal ini lebih fleksibel jika struktur organisasi berubah.

11. Approval Berdasarkan Nominal

Approval bertingkat juga dapat ditentukan berdasarkan nilai transaksi.

Contohnya:

< Rp5 juta
→ Supervisor

Rp5 juta – Rp50 juta
→ Manager

> Rp50 juta
→ Direktur

Alurnya:

Pengajuan
↓
Cek Nominal
↓
Tentukan Approval Level
↓
Buat Workflow

Pendekatan ini cocok untuk sistem procurement dan pengajuan anggaran.

12. Approval Berdasarkan Cabang

Pada sistem multi-cabang:

Cabang Bekasi
↓
Supervisor Bekasi
↓
Manager Regional
↓
Direktur

Tambahkan branch_id pada pengajuan dan approval jika diperlukan.

Contoh:

$table->foreignId('branch_id')
    ->nullable()
    ->constrained();

Dengan demikian, pengajuan dapat diarahkan ke approver berdasarkan cabang.

13. Gunakan Database Transaction

Approval sangat berkaitan dengan perubahan status.

Karena itu gunakan:

DB::transaction(function () {
    // Update approval
    // Update request
});

Jika salah satu proses gagal, perubahan dapat dibatalkan.

14. Hindari Approval Ganda

Dua request dapat masuk hampir bersamaan.

Gunakan transaction dan locking jika proses approval sangat kritis.

Contohnya:

$approval = Approval::where(
    'id',
    $approvalId
)
->lockForUpdate()
->firstOrFail();

Kemudian periksa kembali:

if ($approval->status !== 'pending') {
    abort(
        409,
        'Approval sudah diproses.'
    );
}

Hal ini mencegah satu approval diproses dua kali.

15. Kirim Notifikasi

Setelah Supervisor melakukan approval:

Supervisor
↓
Approve
↓
Manager mendapatkan notifikasi

Laravel Notification dapat digunakan untuk:

  • Email.

  • Database notification.

  • Slack.

  • WhatsApp melalui integrasi.

  • Push notification.

Contoh:

$manager->notify(
    new ApprovalRequiredNotification(
        $requestModel
    )
);

16. Gunakan Queue untuk Notifikasi

Jika notifikasi membutuhkan proses eksternal, gunakan queue:

$manager->notify(
    new ApprovalRequiredNotification(
        $requestModel
    )
);

Notification dapat dibuat menggunakan queue agar proses approval tidak terlalu lama.

17. Audit Log

Setiap approval sebaiknya dicatat.

Contohnya:

User       : Budi
Aktivitas  : Approve
Pengajuan  : PR-001
Level      : Manager
Tanggal    : 23 Agustus 2026
IP Address : 192.168.1.10

Audit log membantu ketika perusahaan perlu mengetahui siapa yang menyetujui atau menolak sebuah pengajuan.

Contoh Alur Lengkap

User membuat pengajuan
        ↓
Status Pending
        ↓
Supervisor
        ↓
Approve
        ↓
Manager
        ↓
Approve
        ↓
Direktur
        ↓
Approve
        ↓
Status Approved

Jika ditolak:

Approver
   ↓
Reject
   ↓
Status Rejected

Approval Bertingkat Bersama Ovla Media

Ovla Media dapat membantu membangun sistem workflow dan approval Laravel untuk:

  1. Approval pembelian.

  2. Approval reimbursement.

  3. Approval cuti.

  4. Approval anggaran.

  5. Approval invoice.

  6. Approval dokumen.

  7. Sistem multi-cabang.

  8. Role dan permission.

  9. Audit log.

  10. Notifikasi otomatis.

Workflow dapat dibuat berdasarkan level jabatan, nominal transaksi, cabang, departemen, maupun jenis pengajuan.

Kesimpulan

Sistem approval bertingkat Laravel dapat dibuat dengan memisahkan data pengajuan dan tahapan approval.

Struktur sederhananya:

Request
   ↓
Approval Level 1
   ↓
Approval Level 2
   ↓
Approval Level 3
   ↓
Approved

Komponen penting yang sebaiknya digunakan:

  1. Approval level.

  2. Role dan permission.

  3. Status approval.

  4. Database transaction.

  5. Locking untuk proses kritis.

  6. Notifikasi.

  7. Audit log.

  8. Idempotency atau pencegahan approval ganda.

Dengan struktur tersebut, sistem dapat dikembangkan untuk berbagai proses bisnis tanpa harus membuat alur approval secara manual untuk setiap jenis pengajuan.

#Approval Laravel #Approval Bertingkat Laravel #Laravel Workflow #Laravel Approval System #Laravel Role Permission #Laravel Notification #Laravel Audit Log #Laravel Multi-Cabang #Sistem Approval #Workflow Approval #Approval Pembelian #Approval Reimbursement #Approval Invoice #Laravel Database Transaction #Laravel Security #PHP Laravel #Aplikasi Bisnis #Web Development #Ovla Media #Jasa Laravel
Beranda Produk Artikel
Konsultasi
OVLA

Navigasi Utama

Hubungi Kami

Mulai Konsultasi Sekarang