342 lines
12 KiB
PHP
342 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Paket;
|
|
use App\Models\Sewa;
|
|
use App\Models\StockModel;
|
|
use App\Models\OngkirKota;
|
|
use App\Models\PaketOngkirKota;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Carbon\Carbon;
|
|
|
|
class SewaController extends Controller
|
|
{
|
|
/**
|
|
* Menampilkan halaman sewa dengan paket yang tersedia
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
// Mengambil paket yang aktif
|
|
$pakets = Paket::where('status', 'aktif')
|
|
->latest()
|
|
->get();
|
|
|
|
return view('sewa', compact('pakets'));
|
|
}
|
|
|
|
/**
|
|
* Menampilkan riwayat sewa
|
|
*/
|
|
public function riwayat(Request $request)
|
|
{
|
|
$query = Sewa::with(['user', 'paket']);
|
|
|
|
// Jika user biasa, hanya tampilkan sewa miliknya
|
|
if (auth()->user()->tipe_pengguna !== 'admin') {
|
|
$query->where('user_id', auth()->id());
|
|
}
|
|
|
|
$sewas = $query->orderBy('created_at', 'desc')->get();
|
|
|
|
return view('sewa.riwayat', [
|
|
'sewas' => $sewas,
|
|
'showDetailPenyewa' => auth()->user()->tipe_pengguna === 'admin'
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Menampilkan form pemesanan paket
|
|
*/
|
|
public function create($id)
|
|
{
|
|
try {
|
|
$paket = Paket::with('ongkirKota')->findOrFail($id);
|
|
|
|
// Cek apakah paket tersedia
|
|
if (!$paket->is_available) {
|
|
return redirect()->route('sewa.index')
|
|
->with('error', 'Maaf, paket ini sedang tidak tersedia.');
|
|
}
|
|
|
|
return view('sewa.create', compact('paket'));
|
|
} catch (\Exception $e) {
|
|
return redirect()->route('sewa.index')
|
|
->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Menyimpan data sewa baru
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
$request->validate([
|
|
'paket_id' => 'required|exists:pakets,id',
|
|
'tanggal_mulai' => 'required|date|after_or_equal:today',
|
|
'tanggal_selesai' => 'required|date|after_or_equal:tanggal_mulai',
|
|
'lokasi' => 'required|string|max:255',
|
|
'kota_id' => 'required|exists:paket_ongkir_kota,id',
|
|
'catatan' => 'nullable|string|max:1000',
|
|
]);
|
|
|
|
try {
|
|
$paket = Paket::findOrFail($request->paket_id);
|
|
|
|
// Cek ketersediaan paket untuk tanggal yang dipilih
|
|
$activeSewa = $paket->sewas()
|
|
->whereIn('status', ['confirmed', 'ongoing'])
|
|
->where(function($query) use ($request) {
|
|
$query->whereBetween('tanggal_mulai', [$request->tanggal_mulai, $request->tanggal_selesai])
|
|
->orWhereBetween('tanggal_selesai', [$request->tanggal_mulai, $request->tanggal_selesai])
|
|
->orWhere(function($q) use ($request) {
|
|
$q->where('tanggal_mulai', '<=', $request->tanggal_mulai)
|
|
->where('tanggal_selesai', '>=', $request->tanggal_selesai);
|
|
});
|
|
})
|
|
->count();
|
|
|
|
if ($activeSewa >= $paket->stok) {
|
|
return back()->with('error', 'Maaf, paket tidak tersedia untuk tanggal yang dipilih.');
|
|
}
|
|
|
|
// Cek minimum order
|
|
$tanggal_mulai = Carbon::parse($request->tanggal_mulai);
|
|
$tanggal_selesai = Carbon::parse($request->tanggal_selesai);
|
|
$durasi = $tanggal_mulai->diffInDays($tanggal_selesai) + 1;
|
|
|
|
if ($paket->minimum_order && $durasi < $paket->minimum_order) {
|
|
return back()->with('error', "Minimum pemesanan untuk paket ini adalah {$paket->minimum_order} hari.");
|
|
}
|
|
|
|
// Validasi kota tujuan
|
|
$kota = PaketOngkirKota::where('id', $request->kota_id)
|
|
->where('paket_id', $request->paket_id)
|
|
->firstOrFail();
|
|
|
|
// Hitung total harga
|
|
$total_harga = ($paket->harga * $durasi) + $kota->biaya_ongkir;
|
|
|
|
// Buat pesanan baru
|
|
$sewa = Sewa::create([
|
|
'user_id' => auth()->id(),
|
|
'paket_id' => $request->paket_id,
|
|
'kota_id' => $kota->id,
|
|
'ongkir' => $kota->biaya_ongkir,
|
|
'tanggal_mulai' => $request->tanggal_mulai,
|
|
'tanggal_selesai' => $request->tanggal_selesai,
|
|
'lokasi' => $request->lokasi,
|
|
'catatan' => $request->catatan,
|
|
'total_harga' => $total_harga,
|
|
'status' => 'pending'
|
|
]);
|
|
|
|
return redirect()->route('sewa.show', $sewa->id)
|
|
->with('success', 'Pesanan berhasil dibuat. Silakan upload bukti pembayaran dan jaminan untuk melanjutkan proses penyewaan.');
|
|
|
|
} catch (\Exception $e) {
|
|
return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function show($id)
|
|
{
|
|
$sewa = Sewa::with(['paket', 'user', 'kota'])->findOrFail($id);
|
|
return view('sewa.show', compact('sewa'));
|
|
}
|
|
|
|
public function uploadBukti(Request $request, $id)
|
|
{
|
|
$request->validate([
|
|
'nominal_pembayaran' => 'required|numeric|min:1',
|
|
'bukti_pembayaran' => 'required|image|max:2048',
|
|
'jenis_jaminan' => 'required|in:ktp,sim',
|
|
'foto_jaminan' => 'required|image|max:2048',
|
|
]);
|
|
|
|
try {
|
|
$sewa = Sewa::findOrFail($id);
|
|
|
|
// Validasi pemilik sewa
|
|
if ($sewa->user_id !== auth()->id()) {
|
|
return back()->with('error', 'Anda tidak memiliki akses untuk mengupload bukti pembayaran ini.');
|
|
}
|
|
|
|
// Validasi status sewa
|
|
if ($sewa->status !== 'pending') {
|
|
return back()->with('error', 'Status sewa tidak valid untuk upload bukti pembayaran.');
|
|
}
|
|
|
|
// Validasi nominal pembayaran
|
|
if ($request->nominal_pembayaran > $sewa->total_harga) {
|
|
return back()->with('error', 'Nominal pembayaran tidak boleh melebihi total harga sewa.');
|
|
}
|
|
|
|
// Upload bukti pembayaran
|
|
if ($request->hasFile('bukti_pembayaran')) {
|
|
if ($sewa->bukti_pembayaran) {
|
|
Storage::disk('public')->delete($sewa->bukti_pembayaran);
|
|
}
|
|
$pathBukti = $request->file('bukti_pembayaran')
|
|
->store('bukti-pembayaran/' . date('Y/m'), 'public');
|
|
}
|
|
|
|
// Upload foto jaminan
|
|
if ($request->hasFile('foto_jaminan')) {
|
|
if ($sewa->foto_jaminan) {
|
|
Storage::disk('public')->delete($sewa->foto_jaminan);
|
|
}
|
|
$pathJaminan = $request->file('foto_jaminan')
|
|
->store('jaminan/' . date('Y/m'), 'public');
|
|
}
|
|
|
|
// Update data sewa
|
|
$sewa->update([
|
|
'bukti_pembayaran' => $pathBukti ?? $sewa->bukti_pembayaran,
|
|
'jenis_jaminan' => $request->jenis_jaminan,
|
|
'foto_jaminan' => $pathJaminan ?? $sewa->foto_jaminan,
|
|
'nominal_pembayaran' => $request->nominal_pembayaran,
|
|
'tanggal_pembayaran' => now(),
|
|
'status' => 'pending'
|
|
]);
|
|
|
|
return redirect()->route('riwayat')
|
|
->with('success', 'Bukti pembayaran dan jaminan berhasil diupload. Mohon tunggu verifikasi dari admin.');
|
|
|
|
} catch (\Exception $e) {
|
|
return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function uploadJaminan(Request $request, $id)
|
|
{
|
|
$request->validate([
|
|
'jenis_jaminan' => 'required|in:ktp,sim',
|
|
'foto_jaminan' => 'required|image|max:2048', // max 2MB
|
|
]);
|
|
|
|
$sewa = Sewa::findOrFail($id);
|
|
|
|
if ($request->hasFile('foto_jaminan')) {
|
|
// Hapus file jaminan lama jika ada
|
|
if ($sewa->foto_jaminan) {
|
|
Storage::disk('public')->delete($sewa->foto_jaminan);
|
|
}
|
|
|
|
// Simpan file jaminan baru
|
|
$path = $request->file('foto_jaminan')->store('jaminan', 'public');
|
|
|
|
// Update data sewa
|
|
$sewa->jenis_jaminan = $request->jenis_jaminan;
|
|
$sewa->foto_jaminan = $path;
|
|
$sewa->save();
|
|
|
|
return redirect()->route('sewa.show', $sewa->id)
|
|
->with('success', 'Jaminan berhasil diupload.');
|
|
}
|
|
|
|
return back()->with('error', 'Terjadi kesalahan saat upload jaminan.');
|
|
}
|
|
|
|
/**
|
|
* Membatalkan penyewaan
|
|
*/
|
|
public function batal($id)
|
|
{
|
|
try {
|
|
$sewa = Sewa::findOrFail($id);
|
|
|
|
// Validasi pemilik sewa
|
|
if ($sewa->user_id !== auth()->id()) {
|
|
return back()->with('error', 'Anda tidak memiliki akses untuk membatalkan penyewaan ini.');
|
|
}
|
|
|
|
// Validasi status sewa
|
|
if (!in_array($sewa->status, ['pending', 'confirmed'])) {
|
|
return back()->with('error', 'Penyewaan tidak dapat dibatalkan karena status sudah ' . $sewa->status_label);
|
|
}
|
|
|
|
// Jika status sudah confirmed, tambahkan catatan pembatalan
|
|
if ($sewa->status === 'confirmed') {
|
|
$sewa->catatan = trim($sewa->catatan . "\n[DIBATALKAN OLEH PENYEWA SETELAH DISETUJUI] - " . now());
|
|
}
|
|
|
|
// Update status menjadi dibatalkan
|
|
$sewa->status = 'dibatalkan';
|
|
$sewa->save();
|
|
|
|
return redirect()->route('riwayat')
|
|
->with('success', 'Penyewaan berhasil dibatalkan.' .
|
|
($sewa->status === 'confirmed' ? ' Mohon hubungi admin untuk informasi biaya pembatalan.' : ''));
|
|
|
|
} catch (\Exception $e) {
|
|
return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mengambil detail sewa untuk ditampilkan di modal
|
|
*/
|
|
public function detail($id)
|
|
{
|
|
try {
|
|
$sewa = Sewa::with(['user', 'paket', 'kota'])
|
|
->findOrFail($id);
|
|
|
|
// Jika bukan admin, pastikan hanya bisa melihat sewa miliknya
|
|
if (auth()->user()->tipe_pengguna !== 'admin' && $sewa->user_id !== auth()->id()) {
|
|
return response()->json([
|
|
'error' => 'Unauthorized'
|
|
], 403);
|
|
}
|
|
|
|
// Format tanggal
|
|
$sewa->tanggal_mulai = Carbon::parse($sewa->tanggal_mulai)->format('d M Y');
|
|
$sewa->tanggal_selesai = Carbon::parse($sewa->tanggal_selesai)->format('d M Y');
|
|
|
|
// Format angka
|
|
$sewa->total_harga = number_format($sewa->total_harga, 0, ',', '.');
|
|
if ($sewa->nominal_pembayaran) {
|
|
$sewa->nominal_pembayaran = number_format($sewa->nominal_pembayaran, 0, ',', '.');
|
|
}
|
|
|
|
return response()->json($sewa);
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'error' => 'Terjadi kesalahan: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function detailJson($id)
|
|
{
|
|
$sewa = Sewa::with(['paket.barangs', 'user', 'kota'])->findOrFail($id);
|
|
return response()->json([
|
|
'id' => $sewa->id,
|
|
'paket' => [
|
|
'nama_paket' => $sewa->paket->nama_paket,
|
|
'jenis_paket' => $sewa->paket->jenis_paket,
|
|
'harga' => $sewa->paket->harga,
|
|
],
|
|
'user' => [
|
|
'nama' => $sewa->user->nama,
|
|
'email' => $sewa->user->email,
|
|
],
|
|
'tanggal_mulai' => $sewa->tanggal_mulai,
|
|
'tanggal_selesai' => $sewa->tanggal_selesai,
|
|
'status' => $sewa->status,
|
|
'total_harga' => $sewa->total_harga,
|
|
'lokasi' => $sewa->lokasi,
|
|
'kota' => $sewa->kota ? $sewa->kota->nama_kota : null,
|
|
'catatan' => $sewa->catatan,
|
|
'barangs' => $sewa->paket->barangs->map(function($barang) {
|
|
return [
|
|
'nama_barang' => $barang->nama_barang,
|
|
'jumlah' => $barang->pivot->jumlah
|
|
];
|
|
}),
|
|
]);
|
|
}
|
|
}
|