orderBy('nama', 'asc')->get(); $lensas = Lensa::orderBy('merek', 'asc')->orderBy('nama', 'asc')->get(); return view('sewa.kamera_index', compact('kameras', 'lensas')); } public function createKamera(Kamera $kamera) { return view('sewa.kamera_form', compact('kamera')); } public function storeKamera(Request $request, Kamera $kamera): RedirectResponse { $today = now()->timezone(config('app.timezone'))->toDateString(); $validated = $request->validate([ 'nama_penyewa' => ['required', 'string', 'max:100'], 'email' => ['required', 'email'], 'telepon' => ['required', 'string', 'max:30'], 'no_wa' => ['required', 'string', 'max:30'], 'alamat_ktp' => ['required', 'string', 'max:500'], 'alamat_tinggal' => ['required', 'string', 'max:500'], 'instagram' => ['nullable', 'string', 'max:100'], 'jaminan' => ['required', 'string', 'max:255'], 'foto_jaminan' => ['required', 'image', 'mimes:jpg,jpeg,png', 'max:'.self::MAX_UPLOAD_FILE_KB], 'foto_diri' => ['required', 'image', 'mimes:jpg,jpeg,png', 'max:'.self::MAX_UPLOAD_FILE_KB], 'member_level' => ['required', 'in:tanpa_member,bronze,silver,gold'], 'qty' => ['required', 'integer', 'min:1', 'max:'.Kamera::DEFAULT_STOCK], 'tanggal_mulai' => ['required', 'date', 'after_or_equal:'.$today], 'tanggal_selesai' => ['required', 'date', 'after_or_equal:tanggal_mulai'], 'jam_sewa' => ['required', 'date_format:H:i'], 'jam_kembali' => ['required', 'date_format:H:i'], 'metode_pembayaran' => ['required', 'in:qris,transfer_bca'], 'bukti_pembayaran' => ['required', 'file', 'mimes:jpg,jpeg,png,pdf', 'max:'.self::MAX_UPLOAD_FILE_KB], 'catatan' => ['nullable', 'string', 'max:500'], ]); $user = $request->user(); $durasiHari = Carbon::parse($validated['tanggal_mulai'])->diffInDays(Carbon::parse($validated['tanggal_selesai'])) + 1; $memberDiskon = [ 'tanpa_member' => 0.00, 'bronze' => 0.05, 'silver' => 0.10, 'gold' => 0.15, ]; $subTotal = $kamera->harga_sewa * $validated['qty'] * $durasiHari; $diskon = (int) round($subTotal * ($memberDiskon[$validated['member_level']] ?? 0)); $totalHarga = max($subTotal - $diskon, 0); $buktiPembayaranPath = $request->file('bukti_pembayaran')->store('bukti-pembayaran', 'public'); $fotoJaminanPath = $request->file('foto_jaminan')->store('foto-jaminan', 'public'); $fotoDiriPath = $request->file('foto_diri')->store('foto-diri', 'public'); if ($user) { $user->update([ 'member_level' => $validated['member_level'], ]); } InventoryStockService::transaction(function () use ( $validated, $user, $kamera, $fotoJaminanPath, $fotoDiriPath, $durasiHari, $totalHarga, $buktiPembayaranPath ): void { InventoryStockService::reserveKamera($kamera, (int) $validated['qty']); Penyewaan::create([ 'user_id' => $user?->id, 'nama_penyewa' => $validated['nama_penyewa'], 'email' => $validated['email'], 'telepon' => $validated['telepon'], 'no_wa' => $validated['no_wa'], 'alamat_ktp' => $validated['alamat_ktp'], 'alamat_tinggal' => $validated['alamat_tinggal'], 'instagram' => $validated['instagram'] ?? null, 'jaminan' => $validated['jaminan'], 'foto_jaminan_path' => $fotoJaminanPath, 'foto_diri_path' => $fotoDiriPath, 'jenis_sewa' => 'kamera', 'member_level' => $validated['member_level'], 'kamera_id' => $kamera->id, 'lensa_id' => null, 'qty' => $validated['qty'], 'tanggal_mulai' => $validated['tanggal_mulai'], 'jam_sewa' => $validated['jam_sewa'], 'tanggal_selesai' => $validated['tanggal_selesai'], 'jam_kembali' => $validated['jam_kembali'], 'durasi_hari' => $durasiHari, 'total_harga' => $totalHarga, 'metode_pembayaran' => $validated['metode_pembayaran'], 'bukti_pembayaran_path' => $buktiPembayaranPath, 'catatan' => $validated['catatan'] ?? null, 'status' => 'menunggu', ]); }); return redirect()->route('sewa.kamera.index')->with('status', 'Penyewaan kamera berhasil diajukan.'); } public function createLensa(Lensa $lensa) { return view('sewa.lensa_form', compact('lensa')); } public function storeLensa(Request $request, Lensa $lensa): RedirectResponse { $today = now()->timezone(config('app.timezone'))->toDateString(); $validated = $request->validate([ 'nama_penyewa' => ['required', 'string', 'max:100'], 'email' => ['required', 'email'], 'telepon' => ['required', 'string', 'max:30'], 'no_wa' => ['required', 'string', 'max:30'], 'alamat_ktp' => ['required', 'string', 'max:500'], 'alamat_tinggal' => ['required', 'string', 'max:500'], 'instagram' => ['nullable', 'string', 'max:100'], 'jaminan' => ['required', 'string', 'max:255'], 'foto_jaminan' => ['required', 'image', 'mimes:jpg,jpeg,png', 'max:'.self::MAX_UPLOAD_FILE_KB], 'foto_diri' => ['required', 'image', 'mimes:jpg,jpeg,png', 'max:'.self::MAX_UPLOAD_FILE_KB], 'member_level' => ['required', 'in:tanpa_member,bronze,silver,gold'], 'qty' => ['required', 'integer', 'min:1', 'max:'.Lensa::DEFAULT_STOCK], 'tanggal_mulai' => ['required', 'date', 'after_or_equal:'.$today], 'tanggal_selesai' => ['required', 'date', 'after_or_equal:tanggal_mulai'], 'jam_sewa' => ['required', 'date_format:H:i'], 'jam_kembali' => ['required', 'date_format:H:i'], 'metode_pembayaran' => ['required', 'in:qris,transfer_bca'], 'bukti_pembayaran' => ['required', 'file', 'mimes:jpg,jpeg,png,pdf', 'max:'.self::MAX_UPLOAD_FILE_KB], 'catatan' => ['nullable', 'string', 'max:500'], ]); $user = $request->user(); $durasiHari = Carbon::parse($validated['tanggal_mulai'])->diffInDays(Carbon::parse($validated['tanggal_selesai'])) + 1; $memberDiskon = [ 'tanpa_member' => 0.00, 'bronze' => 0.05, 'silver' => 0.10, 'gold' => 0.15, ]; $subTotal = $lensa->harga_sewa * $validated['qty'] * $durasiHari; $diskon = (int) round($subTotal * ($memberDiskon[$validated['member_level']] ?? 0)); $totalHarga = max($subTotal - $diskon, 0); $buktiPembayaranPath = $request->file('bukti_pembayaran')->store('bukti-pembayaran', 'public'); $fotoJaminanPath = $request->file('foto_jaminan')->store('foto-jaminan', 'public'); $fotoDiriPath = $request->file('foto_diri')->store('foto-diri', 'public'); if ($user) { $user->update([ 'member_level' => $validated['member_level'], ]); } InventoryStockService::transaction(function () use ( $validated, $user, $lensa, $fotoJaminanPath, $fotoDiriPath, $durasiHari, $totalHarga, $buktiPembayaranPath ): void { InventoryStockService::reserveLensa($lensa, (int) $validated['qty']); Penyewaan::create([ 'user_id' => $user?->id, 'nama_penyewa' => $validated['nama_penyewa'], 'email' => $validated['email'], 'telepon' => $validated['telepon'], 'no_wa' => $validated['no_wa'], 'alamat_ktp' => $validated['alamat_ktp'], 'alamat_tinggal' => $validated['alamat_tinggal'], 'instagram' => $validated['instagram'] ?? null, 'jaminan' => $validated['jaminan'], 'foto_jaminan_path' => $fotoJaminanPath, 'foto_diri_path' => $fotoDiriPath, 'jenis_sewa' => 'lensa', 'member_level' => $validated['member_level'], 'kamera_id' => null, 'lensa_id' => $lensa->id, 'qty' => $validated['qty'], 'tanggal_mulai' => $validated['tanggal_mulai'], 'jam_sewa' => $validated['jam_sewa'], 'tanggal_selesai' => $validated['tanggal_selesai'], 'jam_kembali' => $validated['jam_kembali'], 'durasi_hari' => $durasiHari, 'total_harga' => $totalHarga, 'metode_pembayaran' => $validated['metode_pembayaran'], 'bukti_pembayaran_path' => $buktiPembayaranPath, 'catatan' => $validated['catatan'] ?? null, 'status' => 'menunggu', ]); }); return redirect()->route('sewa.kamera.index')->with('status', 'Penyewaan lensa berhasil diajukan.'); } public function createPaket(Request $request) { $kameras = Kamera::orderBy('merek', 'asc')->orderBy('nama', 'asc')->get(); $lensas = Lensa::orderBy('merek', 'asc')->orderBy('nama', 'asc')->get(); $selectedKamera = $request->integer('kamera_id'); $selectedLensa = $request->integer('lensa_id'); return view('sewa.paket_form', compact('kameras', 'lensas', 'selectedKamera', 'selectedLensa')); } public function storePaket(Request $request): RedirectResponse { $today = now()->timezone(config('app.timezone'))->toDateString(); $validated = $request->validate([ 'nama_penyewa' => ['required', 'string', 'max:100'], 'email' => ['required', 'email'], 'telepon' => ['required', 'string', 'max:30'], 'no_wa' => ['required', 'string', 'max:30'], 'alamat_ktp' => ['required', 'string', 'max:500'], 'alamat_tinggal' => ['required', 'string', 'max:500'], 'instagram' => ['nullable', 'string', 'max:100'], 'jaminan' => ['required', 'string', 'max:255'], 'foto_jaminan' => ['required', 'image', 'mimes:jpg,jpeg,png', 'max:'.self::MAX_UPLOAD_FILE_KB], 'foto_diri' => ['required', 'image', 'mimes:jpg,jpeg,png', 'max:'.self::MAX_UPLOAD_FILE_KB], 'member_level' => ['required', 'in:tanpa_member,bronze,silver,gold'], 'kamera_id' => ['required', 'exists:kameras,id'], 'lensa_id' => ['required', 'exists:lensas,id'], 'qty' => ['required', 'integer', 'min:1', 'max:'.min(Kamera::DEFAULT_STOCK, Lensa::DEFAULT_STOCK)], 'tanggal_mulai' => ['required', 'date', 'after_or_equal:'.$today], 'tanggal_selesai' => ['required', 'date', 'after_or_equal:tanggal_mulai'], 'jam_sewa' => ['required', 'date_format:H:i'], 'jam_kembali' => ['required', 'date_format:H:i'], 'metode_pembayaran' => ['required', 'in:qris,transfer_bca'], 'bukti_pembayaran' => ['required', 'file', 'mimes:jpg,jpeg,png,pdf', 'max:'.self::MAX_UPLOAD_FILE_KB], 'catatan' => ['nullable', 'string', 'max:500'], ]); $user = $request->user(); $kamera = Kamera::findOrFail($validated['kamera_id']); $lensa = Lensa::findOrFail($validated['lensa_id']); $durasiHari = Carbon::parse($validated['tanggal_mulai'])->diffInDays(Carbon::parse($validated['tanggal_selesai'])) + 1; $totalHarian = $kamera->harga_sewa + $lensa->harga_sewa; $memberDiskon = [ 'tanpa_member' => 0.00, 'bronze' => 0.05, 'silver' => 0.10, 'gold' => 0.15, ]; $subTotal = $totalHarian * $validated['qty'] * $durasiHari; $diskon = (int) round($subTotal * ($memberDiskon[$validated['member_level']] ?? 0)); $totalHarga = max($subTotal - $diskon, 0); $buktiPembayaranPath = $request->file('bukti_pembayaran')->store('bukti-pembayaran', 'public'); $fotoJaminanPath = $request->file('foto_jaminan')->store('foto-jaminan', 'public'); $fotoDiriPath = $request->file('foto_diri')->store('foto-diri', 'public'); if ($user) { $user->update([ 'member_level' => $validated['member_level'], ]); } InventoryStockService::transaction(function () use ( $validated, $user, $kamera, $lensa, $fotoJaminanPath, $fotoDiriPath, $durasiHari, $totalHarga, $buktiPembayaranPath ): void { InventoryStockService::reservePaket($kamera, $lensa, (int) $validated['qty']); Penyewaan::create([ 'user_id' => $user?->id, 'nama_penyewa' => $validated['nama_penyewa'], 'email' => $validated['email'], 'telepon' => $validated['telepon'], 'no_wa' => $validated['no_wa'], 'alamat_ktp' => $validated['alamat_ktp'], 'alamat_tinggal' => $validated['alamat_tinggal'], 'instagram' => $validated['instagram'] ?? null, 'jaminan' => $validated['jaminan'], 'foto_jaminan_path' => $fotoJaminanPath, 'foto_diri_path' => $fotoDiriPath, 'jenis_sewa' => 'paket', 'member_level' => $validated['member_level'], 'kamera_id' => $kamera->id, 'lensa_id' => $lensa->id, 'qty' => $validated['qty'], 'tanggal_mulai' => $validated['tanggal_mulai'], 'jam_sewa' => $validated['jam_sewa'], 'tanggal_selesai' => $validated['tanggal_selesai'], 'jam_kembali' => $validated['jam_kembali'], 'durasi_hari' => $durasiHari, 'total_harga' => $totalHarga, 'metode_pembayaran' => $validated['metode_pembayaran'], 'bukti_pembayaran_path' => $buktiPembayaranPath, 'catatan' => $validated['catatan'] ?? null, 'status' => 'menunggu', ]); }); return redirect()->route('sewa.paket.create')->with('status', 'Penyewaan kamera + lensa berhasil diajukan.'); } }