300 lines
12 KiB
PHP
300 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Peminjaman;
|
|
use App\Models\Buku;
|
|
use App\Models\Anggota;
|
|
use Illuminate\Http\Request;
|
|
use Barryvdh\DomPDF\Facade\Pdf;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class AdminPeminjamanController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
$search = $request->input('search');
|
|
|
|
$query = Peminjaman::with(['buku', 'anggota', 'user'])->latest();
|
|
|
|
if ($search) {
|
|
$searchTerm = strtolower($search);
|
|
$query->where(function ($q) use ($searchTerm) {
|
|
$q->whereHas('anggota', function ($qMember) use ($searchTerm) {
|
|
$qMember->whereRaw('LOWER(nama) LIKE ?', ["%{$searchTerm}%"]);
|
|
})->orWhereHas('buku', function ($qBuku) use ($searchTerm) {
|
|
$qBuku->whereRaw('LOWER(judul) LIKE ?', ["%{$searchTerm}%"]);
|
|
})->orWhereHas('user', function ($qUser) use ($searchTerm) {
|
|
$qUser->whereRaw('LOWER(name) LIKE ?', ["%{$searchTerm}%"]);
|
|
});
|
|
});
|
|
}
|
|
|
|
$peminjaman = $query->paginate(15)->appends(['search' => $search]);
|
|
|
|
$buku = Buku::orderBy('judul', 'asc')->get();
|
|
$anggota = Anggota::orderBy('nama', 'asc')->get();
|
|
return view('admin.peminjaman.index', compact('peminjaman', 'buku', 'anggota', 'search'));
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
$buku = Buku::where('eksemplar', '>', 0)->orderBy('judul', 'asc')->get();
|
|
$anggota = Anggota::orderBy('nama', 'asc')->get();
|
|
return view('admin.peminjaman.create', compact('buku', 'anggota'));
|
|
}
|
|
|
|
public function edit($id)
|
|
{
|
|
$peminjaman = Peminjaman::findOrFail($id);
|
|
$buku = Buku::all();
|
|
$anggota = Anggota::orderBy('nama', 'asc')->get();
|
|
return view('admin.peminjaman.edit', compact('peminjaman', 'buku', 'anggota'));
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
// 1. Validasi Input
|
|
$validated = $request->validate([
|
|
'id_anggota' => 'required|exists:anggotas,id',
|
|
'id_buku' => 'required|exists:buku,id_buku',
|
|
'tanggal_pinjam' => 'required|date',
|
|
'tanggal_kembali' => 'required|date|after_or_equal:tanggal_pinjam',
|
|
]);
|
|
|
|
$validated['status_peminjaman'] = 'Dipinjam';
|
|
|
|
// 2. Kurangi Stok Buku
|
|
$buku = Buku::findOrFail($validated['id_buku']);
|
|
$buku->decrement('eksemplar');
|
|
|
|
// 3. Simpan ke Database
|
|
$peminjaman = Peminjaman::create($validated);
|
|
$peminjaman->load(['buku', 'anggota']);
|
|
|
|
$waSuccess = false;
|
|
|
|
// 4. Proses Kirim WA (Format Struk Teks Resmi)
|
|
try {
|
|
$targetNum = $peminjaman->anggota->no_hp ?? '';
|
|
$fonnteToken = 'vpzqxF2ZGgTGz9F5UbUS'; // Token Fonnte
|
|
|
|
// Standarisasi Format Nomor ke awalan 62
|
|
if (!empty($targetNum)) {
|
|
$targetNum = preg_replace('/^0/', '62', trim($targetNum));
|
|
}
|
|
|
|
if (!empty($targetNum) && !empty($fonnteToken)) {
|
|
// Merangkai Teks Menyerupai Struk Kertas
|
|
$pesanStruk = "🏢 *PERPUSTAKAAN DAERAH JEMBER*\n";
|
|
$pesanStruk .= "Jl. Mastrip No. 1, Kabupaten Jember\n";
|
|
$pesanStruk .= "===============================\n\n";
|
|
$pesanStruk .= "📄 *BUKTI PEMINJAMAN BUKU*\n";
|
|
$pesanStruk .= "No. Transaksi : PMJ-{$peminjaman->id_peminjaman}\n";
|
|
$pesanStruk .= "Tanggal Cetak : " . \Carbon\Carbon::now()->format('d-m-Y H:i') . "\n\n";
|
|
$pesanStruk .= "*DATA PEMINJAM*\n";
|
|
$pesanStruk .= "Nama : {$peminjaman->anggota->nama}\n";
|
|
$pesanStruk .= "No. HP : {$peminjaman->anggota->no_hp}\n\n";
|
|
$pesanStruk .= "*DETAIL BUKU*\n";
|
|
$pesanStruk .= "Judul : {$peminjaman->buku->judul}\n";
|
|
$pesanStruk .= "Kode Pengembalian : {$peminjaman->buku->bibid}\n";
|
|
$pesanStruk .= "Pinjam : " . \Carbon\Carbon::parse($peminjaman->tanggal_pinjam)->format('d F Y') . "\n";
|
|
$pesanStruk .= "Kembali: *" . \Carbon\Carbon::parse($peminjaman->tanggal_kembali)->format('d F Y') . "*\n\n";
|
|
$pesanStruk .= "===============================\n";
|
|
$pesanStruk .= "⚠️ *Catatan:*\n";
|
|
$pesanStruk .= "Tunjukkan Kode Pengembalian ke Admin saat pengembalian buku.\n";
|
|
$pesanStruk .= "Harap kembalikan buku tepat waktu.\n";
|
|
$pesanStruk .= "Denda keterlambatan: Rp 1.000/hari.\n\n";
|
|
$pesanStruk .= "Terima kasih atas kunjungan Anda!\n";
|
|
$pesanStruk .= "_Sistem Sarakata - TA 2026_";
|
|
|
|
// Eksekusi Pengiriman via Http Laravel
|
|
$response = \Illuminate\Support\Facades\Http::withoutVerifying()->timeout(15)->withHeaders([
|
|
'Authorization' => $fonnteToken,
|
|
])->post('https://api.fonnte.com/send', [
|
|
'target' => $targetNum,
|
|
'message' => $pesanStruk,
|
|
]);
|
|
|
|
if ($response->successful() && ($response->json('status') == true)) {
|
|
$waSuccess = true;
|
|
}
|
|
}
|
|
} catch (\Exception $e) {
|
|
\Illuminate\Support\Facades\Log::error("Error WA Pengiriman: " . $e->getMessage());
|
|
}
|
|
|
|
// 5. Notifikasi Kembali ke Layar Admin
|
|
$msg = 'Transaksi peminjaman berhasil dicatat.';
|
|
if ($waSuccess) {
|
|
$msg .= ' Struk WA berhasil terkirim kepada Anggota.';
|
|
}
|
|
|
|
return redirect()->route('admin.peminjaman.index')->with('success', $msg);
|
|
}
|
|
|
|
public function cetakStruk($id)
|
|
{
|
|
$peminjaman = Peminjaman::with(['buku', 'anggota', 'user'])->findOrFail($id);
|
|
return view('admin.peminjaman.struk', compact('peminjaman'));
|
|
}
|
|
|
|
public function scan()
|
|
{
|
|
return view('admin.peminjaman.scan');
|
|
}
|
|
|
|
public function prosesScan(Request $request)
|
|
{
|
|
$request->validate(['bibid' => 'required|string']);
|
|
|
|
$buku = Buku::where('bibid', $request->bibid)->first();
|
|
|
|
if (!$buku) {
|
|
return back()->with('error', 'Aset buku tidak ditemukan di dalam database.');
|
|
}
|
|
|
|
$peminjaman = Peminjaman::with(['user', 'anggota'])
|
|
->where('id_buku', $buku->id_buku)
|
|
->where('status_peminjaman', 'Dipinjam')
|
|
->first();
|
|
|
|
if (!$peminjaman) {
|
|
return back()->with('error', 'Buku ini tidak dalam status dipinjam oleh siapapun.');
|
|
}
|
|
|
|
$tanggal_kembali_seharusnya = \Carbon\Carbon::parse($peminjaman->tanggal_kembali);
|
|
$tanggal_dikembalikan_aktual = \Carbon\Carbon::now();
|
|
$denda = 0;
|
|
if ($tanggal_dikembalikan_aktual->gt($tanggal_kembali_seharusnya)) {
|
|
$selisih_hari = $tanggal_dikembalikan_aktual->diffInDays($tanggal_kembali_seharusnya);
|
|
$denda = $selisih_hari * 1000;
|
|
}
|
|
|
|
$lokasi = $this->prediksiLokasiRakUntukAdmin($buku->nomor_panggil);
|
|
|
|
return view('admin.peminjaman.scan', compact('buku', 'peminjaman', 'denda', 'lokasi'));
|
|
}
|
|
|
|
private function prediksiLokasiRakUntukAdmin($nomor_panggil)
|
|
{
|
|
if (empty($nomor_panggil))
|
|
return ['rak' => 'Tidak Diketahui', 'area' => '-'];
|
|
$kode_utama = (int) substr(trim($nomor_panggil), 0, 3);
|
|
|
|
return match (true) {
|
|
$kode_utama >= 0 && $kode_utama <= 99 => match (true) {
|
|
$kode_utama <= 19 => ['rak' => 'Rak 01', 'area' => 'Karya Umum'],
|
|
$kode_utama <= 50 => ['rak' => 'Rak 02', 'area' => 'Karya Umum'],
|
|
default => ['rak' => 'Rak 03-05', 'area' => 'Karya Umum Lainnya'],
|
|
},
|
|
$kode_utama >= 100 && $kode_utama <= 199 => match (true) {
|
|
$kode_utama <= 150 => ['rak' => 'Rak 06-10', 'area' => 'Filsafat'],
|
|
default => ['rak' => 'Rak 11-14', 'area' => 'Psikologi'],
|
|
},
|
|
$kode_utama >= 200 && $kode_utama <= 299 => match (true) {
|
|
$kode_utama == 297 => ['rak' => 'Rak 25-32', 'area' => 'Agama Islam'],
|
|
default => ['rak' => 'Rak 15-24', 'area' => 'Agama Umum'],
|
|
},
|
|
$kode_utama >= 300 && $kode_utama <= 399 => match (true) {
|
|
$kode_utama <= 330 => ['rak' => 'Rak 33-36', 'area' => 'Sosiologi & Politik'],
|
|
$kode_utama <= 360 => ['rak' => 'Rak 37-40', 'area' => 'Ekonomi & Hukum'],
|
|
default => ['rak' => 'Rak 41-44', 'area' => 'Pendidikan & Adat'],
|
|
},
|
|
$kode_utama >= 400 && $kode_utama <= 499 => ['rak' => 'Rak 45', 'area' => 'Bahasa'],
|
|
$kode_utama >= 500 && $kode_utama <= 599 => ['rak' => 'Rak 46-48', 'area' => 'Ilmu Murni'],
|
|
$kode_utama >= 600 && $kode_utama <= 699 => match (true) {
|
|
$kode_utama <= 610 => ['rak' => 'Rak 49-53', 'area' => 'Kedokteran'],
|
|
$kode_utama <= 630 => ['rak' => 'Rak 54-58', 'area' => 'Teknik'],
|
|
$kode_utama <= 650 => ['rak' => 'Rak 59-63', 'area' => 'Pertanian'],
|
|
default => ['rak' => 'Rak 64-68', 'area' => 'Manajemen Bisnis'],
|
|
},
|
|
$kode_utama >= 700 && $kode_utama <= 799 => match (true) {
|
|
$kode_utama <= 739 => ['rak' => 'Rak 71', 'area' => 'Kesenian'],
|
|
$kode_utama <= 769 => ['rak' => 'Rak 72', 'area' => 'Seni Rupa'],
|
|
$kode_utama <= 789 => ['rak' => 'Rak 73', 'area' => 'Fotografi/Musik'],
|
|
default => ['rak' => 'Rak 74', 'area' => 'Olahraga'],
|
|
},
|
|
$kode_utama >= 800 && $kode_utama <= 899 => ['rak' => 'Rak 77-79', 'area' => 'Sastra'],
|
|
$kode_utama >= 900 && $kode_utama <= 999 => match (true) {
|
|
$kode_utama <= 919 => ['rak' => 'Rak 69, 70', 'area' => 'Geografi'],
|
|
default => ['rak' => 'Rak 80-84', 'area' => 'Sejarah Umum'],
|
|
},
|
|
default => ['rak' => 'Rak 75-76', 'area' => 'Koleksi Terbaru'],
|
|
};
|
|
}
|
|
|
|
public function update(Request $request, $id)
|
|
{
|
|
$validated = $request->validate([
|
|
'id_anggota' => 'required|exists:anggotas,id',
|
|
'id_buku' => 'required|exists:buku,id_buku',
|
|
'tanggal_pinjam' => 'required|date',
|
|
'tanggal_kembali' => 'required|date|after_or_equal:tanggal_pinjam',
|
|
]);
|
|
|
|
$peminjaman = Peminjaman::findOrFail($id);
|
|
|
|
// If the book changed, adjust stock
|
|
if ($peminjaman->id_buku != $validated['id_buku']) {
|
|
if ($peminjaman->status_peminjaman == 'Dipinjam') {
|
|
$oldBuku = Buku::find($peminjaman->id_buku);
|
|
if ($oldBuku) $oldBuku->increment('eksemplar');
|
|
|
|
$newBuku = Buku::findOrFail($validated['id_buku']);
|
|
$newBuku->decrement('eksemplar');
|
|
}
|
|
}
|
|
|
|
$peminjaman->update($validated);
|
|
|
|
return redirect()->route('admin.peminjaman.index')->with('success', 'Data peminjaman berhasil diperbarui.');
|
|
}
|
|
|
|
public function destroy($id)
|
|
{
|
|
$peminjaman = Peminjaman::findOrFail($id);
|
|
|
|
if ($peminjaman->status_peminjaman == 'Dipinjam' && $peminjaman->buku) {
|
|
$peminjaman->buku->increment('eksemplar');
|
|
}
|
|
|
|
$peminjaman->delete();
|
|
|
|
return redirect()->route('admin.peminjaman.index')->with('success', 'Data peminjaman berhasil dihapus.');
|
|
}
|
|
|
|
public function kembalikan($id)
|
|
{
|
|
$peminjaman = Peminjaman::findOrFail($id);
|
|
|
|
$tglTenggat = \Carbon\Carbon::parse($peminjaman->tanggal_kembali)->startOfDay();
|
|
$tglSekarang = \Carbon\Carbon::now()->startOfDay();
|
|
|
|
$denda = 0;
|
|
if ($tglSekarang->gt($tglTenggat)) {
|
|
$selisihHari = $tglSekarang->diffInDays($tglTenggat);
|
|
$denda = $selisihHari * 1000;
|
|
}
|
|
|
|
$peminjaman->update([
|
|
'status_peminjaman' => 'Dikembalikan',
|
|
'tanggal_dikembalikan' => now(),
|
|
'denda' => $denda
|
|
]);
|
|
|
|
if ($peminjaman->buku) {
|
|
$peminjaman->buku->increment('eksemplar');
|
|
}
|
|
|
|
$pesan = 'Buku berhasil dikembalikan.';
|
|
if ($denda > 0) {
|
|
$pesan .= ' Denda keterlambatan Rp ' . number_format($denda, 0, ',', '.');
|
|
}
|
|
|
|
return redirect()->back()->with('success', $pesan);
|
|
}
|
|
}
|