I’m working on a payment feature in Laravel, but I’m facing an issue with the change (kembalian) calculation.
When a user pays exactly the same amount as the total bill (total_tagihan, the change is incorrectly set to the total bill amount instead of 0.
public function bayar(Request $request)
{
Log::info('Fungsi bayar() dipanggil', ['request' => $request->all()]);
$request->validate([
'nomor_pelanggan' => 'required|exists:pelanggans,nomor_pelanggan',
'total_bayar' => 'required|numeric|min:0',
'jumlah_dibayar' => 'required|numeric|min:0',
]);
Log::info('Validasi berhasil', ['data' => $request->all()]);
$pelanggan = Pelanggan::where('nomor_pelanggan', $request->nomor_pelanggan)->first();
if (!$pelanggan) {
Log::error('Pelanggan tidak ditemukan!', ['nomor_pelanggan' => $request->nomor_pelanggan]);
return back()->with('error', 'Pelanggan tidak ditemukan.');
}
Log::info('Pelanggan ditemukan', ['pelanggan' => $pelanggan]);
// Ambil data pemakaian pelanggan
$pemakaians = CatatanPemakaian::where('nomor_pelanggan', $request->nomor_pelanggan)->get();
$total_pemakaian = $pemakaians->sum('jumlah_penggunaan') ?? 0;
// Hitung denda
$total_denda = abs(Pembayaran::hitungDenda($request->nomor_pelanggan));
Log::info('Denda dihitung', ['total_denda' => $total_denda]);
// Pastikan biaya admin dan abodemen memiliki nilai
$biaya_admin = $request->biaya_admin ?? 2500;
// Cari data pembayaran terakhir untuk mendapatkan biaya abodemen
$pembayaranTerakhir = Pembayaran::where('nomor_pelanggan', $request->nomor_pelanggan)
->orderBy('id', 'desc')
->first();
$biaya_abodemen = $pembayaranTerakhir->biaya_abodemen ?? 0;
// Hitung total yang harus dibayar
$total_pembayaran = $request->total_tagihan + $total_denda + $biaya_admin + $biaya_abodemen;
Log::info('Total pembayaran dari form', ['total_pembayaran' => $total_pembayaran]);
$jumlah_dibayar = $request->jumlah_dibayar;
$kembalian = $jumlah_dibayar - $total_pembayaran;
Log::info('Total sebelum simpan', [
'total_tagihan' => $request->total_tagihan,
'total_denda' => $total_denda,
'biaya_admin' => $biaya_admin,
'biaya_abodemen' => $biaya_abodemen,
'total_pembayaran' => $total_pembayaran,
]);
if ($jumlah_dibayar < $total_pembayaran) {
Log::error('Pembayaran gagal: Uang kurang', [
'jumlah_dibayar' => $jumlah_dibayar,
'total_pembayaran' => $total_pembayaran
]);
return back()->with('error', 'Uang yang dibayarkan kurang dari jumlah tagihan.');
}
try {
// Simpan pembayaran
$pembayaran = Pembayaran::create([
'nomor_pelanggan' => $request->nomor_pelanggan,
'total_pemakaian' => $total_pemakaian, // ← FIXED: Total pemakaian sekarang sudah ada
'total_tagihan' => $request->total_bayar - $total_denda - $biaya_admin - $biaya_abodemen,
'biaya_admin' => $biaya_admin,
'biaya_abodemen' => $biaya_abodemen,
'jumlah_dibayar' => $jumlah_dibayar,
'tanggal_pembayaran' => now(),
'denda' => $total_denda,
'kembalian' => $kembalian,
]);
Log::info('Pembayaran berhasil disimpan', ['pembayaran' => $pembayaran]);
Log::info('Total tagihan:', ['total_tagihan' => $request->total_tagihan]);
Log::info('Total denda:', ['total_denda' => $total_denda]);
Log::info('Biaya admin:', ['biaya_admin' => $biaya_admin]);
Log::info('Biaya abodemen:', ['biaya_abodemen' => $biaya_abodemen]);
Log::info('Total pembayaran yang dihitung:', ['total_pembayaran' => $total_pembayaran]);
// Update status pemakaian yang sudah dibayar
foreach ($pemakaians as $pemakaian) {
$pemakaian->id = $pembayaran->id;
$pemakaian->save();
}
// Update tanggal pembayaran terakhir pelanggan
$pelanggan->tanggal_pembayaran_terakhir = now();
$pelanggan->save();
Log::info('Tanggal pembayaran pelanggan diperbarui');
return redirect()->route('invoice.list')->with('success', 'Pembayaran berhasil! Kembalian: Rp ' . number_format($kembalian, 0, ',', '.'));
} catch (Exception $e) {
Log::error('Terjadi error saat menyimpan pembayaran', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
return back()->with('error', 'Terjadi kesalahan saat memproses pembayaran: ' . $e->getMessage());
}
}

The change successfully fixed the issue, and the refund amount is now correct