filled('search')) { $search = $request->search; $query->where(function ($q) use ($search) { $q->where('title', 'like', "%{$search}%") ->orWhere('sor', 'like', "%{$search}%") ->orWhere('classification', 'like', "%{$search}%") ->orWhere('kode_eksemplar', 'like', "%{$search}%"); }); } $results = $query->orderBy('input_date', 'desc') ->paginate(20) ->withQueryString(); return view('admin.koleksi.index', compact('results')); } public function create() { $publishers = Publisher::all(); $publishPlaces = PublishPlace::all(); return view('admin.koleksi.create', compact('publishers', 'publishPlaces')); } public function store(Request $request) { $request->validate([ 'title' => 'required|string|max:255', 'sor' => 'nullable|string|max:255', 'jumlah_eksemplar' => 'required|integer|min:1', 'publisher_name' => 'nullable|string|max:255', 'publish_place_name' => 'nullable|string|max:255', 'publish_year' => 'nullable|integer', 'isbn_issn' => 'nullable|string|max:50', 'edition' => 'nullable|string|max:100', 'classification' => 'nullable|string|max:100', 'labels' => 'nullable|string|max:255', 'image' => 'nullable|file|mimes:jpg,jpeg,png,gif', 'opac_hide' => 'nullable|boolean', 'promoted' => 'nullable|boolean', ]); $jumlah = $request->jumlah_eksemplar; $imagePath = $request->hasFile('image') ? $request->file('image')->store('images', 'public') : null; for ($i = 1; $i <= $jumlah; $i++) { $kodeEksemplar = $this->generateKodeEksemplar(); $barcodePath = $this->generateBarcode($kodeEksemplar); Koleksi::create([ 'title' => $request->title, 'sor' => $request->sor, 'publisher_name' => $request->publisher_name, 'publish_place_name' => $request->publish_place_name, 'publish_year' => $request->publish_year, // 🔥 FIX WAJIB 'tahun_terbit' => $request->publish_year, 'isbn_issn' => $request->isbn_issn, 'edition' => $request->edition, 'classification' => $request->classification, 'labels' => $request->labels, 'image' => $imagePath, 'barcode' => $barcodePath, 'kode_eksemplar' => $kodeEksemplar, 'input_date' => now(), 'last_update' => now(), 'uid' => auth()->id(), 'opac_hide' => $request->opac_hide ?? 0, 'promoted' => $request->promoted ?? 0, ]); } return redirect()->route('admin.koleksi.index') ->with('success', '✅ Koleksi berhasil ditambahkan dengan Barcode.'); } protected function generateKodeEksemplar() { do { $random = str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); $kode = 'P' . $random . 'S'; } while (Koleksi::where('kode_eksemplar', $kode)->exists()); return $kode; } protected function generateBarcode($kodeEksemplar) { $barcode = new DNS1D(); $barcode->setStorPath(storage_path('app/public/barcodes')); if (!Storage::disk('public')->exists('barcodes')) { Storage::disk('public')->makeDirectory('barcodes'); } $barcodePng = $barcode->getBarcodePNG($kodeEksemplar, 'C39+', 3, 100); $barcodePath = "barcodes/{$kodeEksemplar}.png"; Storage::disk('public')->put($barcodePath, base64_decode($barcodePng)); return $barcodePath; } public function printBarcodeSingle($kode_eksemplar) { $koleksi = Koleksi::where('kode_eksemplar', $kode_eksemplar)->firstOrFail(); $setting = Setting::first(); $pdf = Pdf::loadView('admin.koleksi.label_barcode_single', compact('koleksi', 'setting')) ->setPaper([0, 0, 200, 120], 'portrait'); return $pdf->stream("barcode_{$koleksi->kode_eksemplar}.pdf"); } public function printBarcodeMultiple(Request $request) { $selected = $request->input('selected', []); if (!is_array($selected)) { $selected = explode(',', $selected); } if (empty($selected)) { return redirect()->back()->with('error', 'Pilih minimal satu koleksi untuk dicetak.'); } $koleksiList = Koleksi::whereIn('kode_eksemplar', $selected)->get(); $setting = Setting::first(); $pdf = Pdf::loadView('admin.koleksi.label_barcode_multiple', compact('koleksiList', 'setting')) ->setPaper('a4', 'portrait'); return $pdf->stream("barcode_massal.pdf"); } public function edit($kode_eksemplar) { $koleksi = Koleksi::where('kode_eksemplar', $kode_eksemplar)->firstOrFail(); $publishers = Publisher::all(); $publishPlaces = PublishPlace::all(); return view('admin.koleksi.edit', compact('koleksi', 'publishers', 'publishPlaces')); } public function update(Request $request, $kode_eksemplar) { $koleksi = Koleksi::where('kode_eksemplar', $kode_eksemplar)->firstOrFail(); $request->validate([ 'title' => 'required|string|max:255', 'sor' => 'nullable|string|max:255', 'publisher_name' => 'nullable|string|max:255', 'publish_place_name' => 'nullable|string|max:255', 'publish_year' => 'nullable|integer', 'isbn_issn' => 'nullable|string|max:50', 'edition' => 'nullable|string|max:100', 'classification' => 'nullable|string|max:100', 'labels' => 'nullable|string|max:255', 'image' => 'nullable|file|mimes:jpg,jpeg,png,gif', 'opac_hide' => 'nullable|boolean', 'promoted' => 'nullable|boolean', ]); if ($request->hasFile('image')) { if ($koleksi->image) { Storage::disk('public')->delete($koleksi->image); } $koleksi->image = $request->file('image')->store('images', 'public'); } $koleksi->update([ 'title' => $request->title, 'sor' => $request->sor, 'publisher_name' => $request->publisher_name, 'publish_place_name' => $request->publish_place_name, 'publish_year' => $request->publish_year, // 🔥 FIX WAJIB 'tahun_terbit' => $request->publish_year, 'isbn_issn' => $request->isbn_issn, 'edition' => $request->edition, 'classification' => $request->classification, 'labels' => $request->labels, 'image' => $koleksi->image, 'opac_hide' => $request->opac_hide ?? 0, 'promoted' => $request->promoted ?? 0, 'last_update' => now(), ]); return redirect()->route('admin.koleksi.index') ->with('success', '✅ Data koleksi berhasil diperbarui.'); } public function destroy($kode_eksemplar) { $koleksi = Koleksi::where('kode_eksemplar', $kode_eksemplar)->firstOrFail(); if ($koleksi->image) { // Cek apakah ada eksemplar LAIN yang masih menggunakan gambar ini $fotoMasihDipakai = Koleksi::where('image', $koleksi->image) ->where('kode_eksemplar', '!=', $kode_eksemplar) ->exists(); // Jika tidak ada eksemplar lain yang pakai, baru hapus file fisiknya if (!$fotoMasihDipakai) { Storage::disk('public')->delete($koleksi->image); } } // Barcode tetap langsung dihapus karena setiap eksemplar punya barcode unik if ($koleksi->barcode) { Storage::disk('public')->delete($koleksi->barcode); } $koleksi->delete(); return redirect()->route('admin.koleksi.index') ->with('success', '✅ Koleksi berhasil dihapus.'); } // ... (di dalam KoleksiController) public function printMultipleBarcode(Request $request) { // 1. Validasi input if (!$request->has('kode_eksemplar') || !is_array($request->kode_eksemplar)) { return redirect()->back()->with('error', 'Silakan centang minimal satu koleksi terlebih dahulu.'); } $kodeEksemplarArray = $request->kode_eksemplar; // --- BAGIAN INI DIPERBAIKI --- // Mengurutkan data agar sama persis dengan urutan centang (array input) $orderList = "'" . implode("','", $kodeEksemplarArray) . "'"; $items = Koleksi::whereIn('kode_eksemplar', $kodeEksemplarArray) ->orderByRaw("FIELD(kode_eksemplar, $orderList)") ->get(); // ----------------------------- if ($items->isEmpty()) { return redirect()->back()->with('error', 'Data koleksi yang Anda pilih tidak ditemukan.'); } $setting = Setting::first(); // 2. Render PDF $pdf = Pdf::loadView('admin.koleksi.barcode_multiple', compact('items', 'setting')); // 3. Atur kertas $pdf->setPaper('a4', 'portrait'); // 4. Stream PDF return $pdf->stream('Label_Barcode_Massal.pdf'); } public function destroyMultiple(Request $request) { $kodese = $request->input('kode_eksemplar', []); if (empty($kodese)) { return redirect()->back()->with('error', 'Tidak ada item yang dipilih.'); } // Ambil semua data koleksi yang kodenya sesuai array $koleksis = Koleksi::whereIn('kode_eksemplar', $kodese)->get(); foreach ($koleksis as $koleksi) { // Contoh logika hapus file cover jika tidak dipakai eksemplar lain if ($koleksi->image) { $fotoMasihDipakai = Koleksi::where('image', $koleksi->image) ->whereNotIn('kode_eksemplar', $kodese) ->exists(); if (!$fotoMasihDipakai) { Storage::disk('public')->delete($koleksi->image); } } // Hapus file barcode asli jika disimpan fisik if ($koleksi->barcode) { Storage::disk('public')->delete($koleksi->barcode); } $koleksi->delete(); } return redirect()->route('admin.koleksi.index')->with('success', count($kodese) . ' data koleksi berhasil dihapus sekaligus.'); } }