Tutorial #5: API Transaksi Nabung dan Tarik Tunai oleh Petugas
Halo calon teller bank! Hari ini kita akan membuat API untuk transaksi setor dan tarik tunai. Petugas bisa melayani nasabah yang mau nabung atau ambil uang. Siapkan buku tabungan virtual!
Yang akan kita buat:
- ✅ Controller khusus transaksi (TransactionController).
- ✅ Endpoint
/api/deposituntuk setor tunai. - ✅ Endpoint
/api/withdrawuntuk tarik tunai. - ✅ Validasi: jumlah > 0, saldo cukup (untuk tarik), rekening ada.
- ✅ Update saldo di tabel accounts.
- ✅ Catat transaksi ke tabel transactions dengan petugas_id.
- ✅ Route dilindungi middleware isPetugas (hanya petugas yang bisa).
Langkah 1: Membuat TransactionController
Buka terminal di folder bank-backend, jalankan perintah:
php artisan make:controller Api/TransactionController
File akan muncul di app/Http/Controllers/Api/TransactionController.php. Kita akan isi dengan method deposit dan withdraw.
mutasi untuk melihat riwayat transaksi per rekening, tapi itu akan kita bahas di artikel terpisah (atau bisa di sini sekalian).
Langkah 2: Method Deposit (Setor Tunai)
Method deposit menerima input: account_id atau nomor rekening, amount, dan description (opsional). Petugas yang login otomatis menjadi pencatat.
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Account;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class TransactionController extends Controller
{
public function deposit(Request $request)
{
$request->validate([
'account_id' => 'required|exists:accounts,id',
'amount' => 'required|numeric|min:1000', // minimal seribu, biar nggak receh
'description' => 'nullable|string|max:255',
]);
// Gunakan database transaction agar kalau error, saldo nggak berubah
DB::beginTransaction();
try {
$account = Account::findOrFail($request->account_id);
// Update saldo (debit = nambah)
$account->balance += $request->amount;
$account->save();
// Catat transaksi
$transaction = Transaction::create([
'account_id' => $account->id,
'type' => 'debit', // debit = setor (uang masuk)
'amount' => $request->amount,
'description' => $request->description ?? 'Setor tunai',
'petugas_id' => auth()->id(), // id petugas yang login
]);
DB::commit();
return response()->json([
'message' => 'Setor tunai berhasil!',
'account' => $account,
'transaction' => $transaction->load('petugas'),
], 200);
} catch (\Exception $e) {
DB::rollBack();
return response()->json(['message' => 'Transaksi gagal: ' . $e->getMessage()], 500);
}
}
}
Penjelasan:
- Validasi memastikan account_id ada di tabel accounts dan amount minimal 1000.
DB::beginTransaction()untuk memastikan jika ada kesalahan, saldo tidak berubah.- Saldo ditambah, kemudian simpan transaksi dengan type 'debit'.
- petugas_id diambil dari user yang sedang login (pastikan route memakai auth:sanctum).
Langkah 3: Method Withdraw (Tarik Tunai)
Method withdraw hampir sama, tapi saldo dikurang dan harus cek kecukupan saldo.
public function withdraw(Request $request)
{
$request->validate([
'account_id' => 'required|exists:accounts,id',
'amount' => 'required|numeric|min:1000',
'description' => 'nullable|string|max:255',
]);
DB::beginTransaction();
try {
$account = Account::findOrFail($request->account_id);
// Cek saldo cukup
if ($account->balance < $request->amount) {
return response()->json(['message' => 'Saldo tidak cukup!'], 400);
}
// Update saldo (kredit = berkurang)
$account->balance -= $request->amount;
$account->save();
// Catat transaksi
$transaction = Transaction::create([
'account_id' => $account->id,
'type' => 'kredit', // kredit = tarik (uang keluar)
'amount' => $request->amount,
'description' => $request->description ?? 'Tarik tunai',
'petugas_id' => auth()->id(),
]);
DB::commit();
return response()->json([
'message' => 'Tarik tunai berhasil!',
'account' => $account,
'transaction' => $transaction->load('petugas'),
], 200);
} catch (\Exception $e) {
DB::rollBack();
return response()->json(['message' => 'Transaksi gagal: ' . $e->getMessage()], 500);
}
}
Langkah 4: Menambahkan Route dengan Middleware isPetugas
Buka routes/api.php. Di dalam group middleware auth:sanctum kita buat group khusus untuk petugas. Tambahkan:
Route::middleware('auth:sanctum')->group(function () {
// ... route logout, user, dll yang sudah ada
Route::middleware('isPetugas')->group(function () {
Route::post('/deposit', [App\Http\Controllers\Api\TransactionController::class, 'deposit']);
Route::post('/withdraw', [App\Http\Controllers\Api\TransactionController::class, 'withdraw']);
});
});
Dengan ini, hanya user dengan role_id = 2 (petugas) yang bisa mengakses endpoint deposit dan withdraw.
isPetugas sudah didaftarkan di Kernel. Kalau belum, lihat tutorial #3.
Langkah 5: Uji Coba dengan Postman
Login sebagai petugas: POST ke /api/login dengan email petugas@bank.com (atau email petugas yang sudah dibuat) dan password. Copy token.
Set Authorization: Bearer Token dengan token tadi.
Uji deposit: POST ke /api/deposit dengan JSON:
{
"account_id": 1,
"amount": 50000,
"description": "Setor tunai dari Andi"
}
Respons sukses akan mengembalikan data akun dan transaksi.
Uji withdraw: POST ke /api/withdraw dengan data serupa, pastikan saldo cukup.
Coba juga akses endpoint ini menggunakan token admin atau nasabah, harusnya ditolak (403).
Bonus: Melihat Mutasi Transaksi per Rekening
Petugas atau nasabah mungkin perlu melihat riwayat transaksi. Kita bisa tambahkan method mutasi di TransactionController.
Tambahkan method ini:
public function mutasi($account_id)
{
$account = Account::findOrFail($account_id);
$transactions = $account->transactions()->with('petugas')->latest()->get();
return response()->json([
'account' => $account,
'transactions' => $transactions,
]);
}
Dan route-nya (dalam group auth:sanctum, bisa diakses oleh pemilik akun dan petugas? Nanti kita atur policy. Untuk sederhana, kita letakkan di group petugas dulu):
Route::middleware('isPetugas')->group(function () {
// ...
Route::get('/mutasi/{account_id}', [App\Http\Controllers\Api\TransactionController::class, 'mutasi']);
});
Nanti nasabah juga bisa lihat mutasi sendiri melalui endpoint terpisah (akan dibuat di tutorial frontend).
Kesimpulan
- ✅ Endpoint deposit dan withdraw siap digunakan petugas.
- ✅ Transaksi dicatat dengan type debit/kredit dan petugas_id.
- ✅ Saldo otomatis berubah.
- ✅ Validasi mencegah saldo negatif.
Di tutorial selanjutnya (#6: API Laporan Mutasi Rekening dan Total Saldo Nasabah) kita akan membuat endpoint khusus untuk nasabah melihat saldo dan riwayat transaksi mereka. Siap-siap jadi frontend developer!