MIF_E31231430/app/Http/Controllers/PenyewaanController.php

329 lines
15 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Kamera;
use App\Models\Lensa;
use App\Models\Penyewaan;
use App\Services\InventoryStockService;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Carbon;
class PenyewaanController extends Controller
{
private const MAX_UPLOAD_FILE_KB = 2048;
public function indexKamera()
{
$kameras = Kamera::orderBy('merek', 'asc')->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.');
}
}