NIM_E31222518/app/Http/Controllers/KeranjangController.php

682 lines
26 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Barang;
use App\Models\Keranjang;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class KeranjangController extends Controller
{
/**
* Display keranjang belanja user
*/
public function index(Request $request)
{
$items = Keranjang::with('barang')
->where('user_id', Auth::id())
->latest()
->get();
$total = $items->sum('total_harga');
// Jika ini adalah request verifikasi, kirim respons khusus tanpa view
if ($request->has('verify')) {
// Kirim data sebagai JSON jika diminta
if ($request->ajax()) {
return response()->json([
'items' => $items->map(function($item) {
return [
'id' => $item->id,
'jumlah' => $item->jumlah,
'total_harga' => $item->total_harga,
'harga_satuan' => $item->barang->harga
];
}),
'total' => $total,
'timestamp' => now()->timestamp
]);
}
// Jika bukan request AJAX, kirim respons sederhana
return response('OK', 200);
}
return view('keranjang.index', compact('items', 'total'));
}
/**
* Tambah item ke keranjang
*/
public function tambah(Request $request)
{
$request->validate([
'barang_id' => 'required|exists:barang,id',
'jumlah' => 'required|integer|min:1',
]);
$barang = Barang::findOrFail($request->barang_id);
// Validasi stok
if ($request->jumlah > $barang->stok) {
return redirect()->back()
->with('error', 'Jumlah melebihi stok yang tersedia');
}
// Cek jika barang sudah ada di keranjang
$item = Keranjang::where('user_id', Auth::id())
->where('barang_id', $request->barang_id)
->first();
if ($item) {
// Update jumlah dan total harga
$newJumlah = $item->jumlah + $request->jumlah;
// Cek stok sekali lagi
if ($newJumlah > $barang->stok) {
return redirect()->back()
->with('error', 'Total jumlah melebihi stok yang tersedia');
}
$item->jumlah = $newJumlah;
$item->total_harga = $barang->harga * $newJumlah;
$item->save();
} else {
// Buat item baru di keranjang
Keranjang::create([
'user_id' => Auth::id(),
'barang_id' => $request->barang_id,
'jumlah' => $request->jumlah,
'total_harga' => $barang->harga * $request->jumlah,
]);
}
return redirect()->route('keranjang.index')
->with('success', 'Barang berhasil ditambahkan ke keranjang');
}
/**
* Update jumlah item di keranjang
*/
public function update(Request $request, Keranjang $keranjang)
{
// Logging untuk debugging request method
\Log::debug('Update Keranjang Request: ', [
'method' => $request->method(),
'real_method' => $request->getRealMethod(),
'has_method_field' => $request->has('_method'),
'method_field' => $request->input('_method'),
'route' => $request->route()->getName(),
'item_id' => $keranjang->id,
'user_id' => Auth::id()
]);
$request->validate([
'jumlah' => 'required|integer|min:1',
]);
// Validasi kepemilikan dengan logging
if ($keranjang->user_id !== Auth::id()) {
\Log::warning('Akses tidak sah: User '.Auth::id().' mencoba mengakses keranjang '.$keranjang->id.' milik user '.$keranjang->user_id);
if ($request->ajax()) {
return response()->json(['success' => false, 'message' => 'Tidak diizinkan'], 403);
}
abort(403);
}
$barang = $keranjang->barang;
// Validasi stok
if ($request->jumlah > $barang->stok) {
if ($request->ajax()) {
return response()->json(['success' => false, 'message' => 'Jumlah melebihi stok yang tersedia']);
}
return redirect()->back()
->with('error', 'Jumlah melebihi stok yang tersedia');
}
// Deteksi apakah ini request konfirmasi
$isConfirm = $request->has('is_confirm_submit');
// Prioritaskan request konfirmasi atau nonaktifkan cache di browser
// Pastikan perubahan tersimpan ke database dalam semua kasus
$keranjang->jumlah = $request->jumlah;
$keranjang->total_harga = $barang->harga * $request->jumlah;
$result = $keranjang->save();
// Log untuk debugging
\Log::info('Keranjang diupdate: ID=' . $keranjang->id .
', Jumlah=' . $request->jumlah .
', IsConfirm=' . ($isConfirm ? 'Ya' : 'Tidak') .
', Hasil=' . ($result ? 'Sukses' : 'Gagal'));
// Handle jika ini adalah iframe request
if ($request->has('is_js_request')) {
// Kembalikan HTML minimal untuk iframe
return response('<html><body><script>parent.postMessage("update_success", "*");</script></body></html>');
}
if ($request->ajax()) {
return response()->json([
'success' => true,
'message' => 'Keranjang berhasil diperbarui',
'total_harga' => $keranjang->total_harga,
'jumlah' => $keranjang->jumlah
]);
}
// Jika ini request konfirmasi, buat respons khusus yang mengindikasikan sukses
if ($isConfirm) {
return response()->json(['success' => true, 'confirmed' => true]);
}
return redirect()->route('keranjang.index')
->with('success', 'Keranjang berhasil diperbarui');
}
/**
* Hapus item dari keranjang
*/
public function hapus(Request $request, Keranjang $keranjang)
{
try {
// Debug logging
\Log::debug('Mencoba menghapus keranjang: ID=' . $keranjang->id .
', Auth::id()=' . Auth::id() .
', keranjang->user_id=' . $keranjang->user_id .
', sama=' . ((Auth::id() === $keranjang->user_id) ? 'Ya' : 'Tidak'));
// Log semua parameter request
\Log::debug('Request data: ' . json_encode($request->all()));
// Validasi kepemilikan dengan logging
if ($keranjang->user_id !== Auth::id()) {
\Log::warning('Akses tidak sah: User '.Auth::id().' mencoba menghapus keranjang '.$keranjang->id.' milik user '.$keranjang->user_id);
if ($request->ajax() || $request->has('is_js_request')) {
return response('<html><body><script>parent.postMessage("delete_error", "*");</script></body></html>');
}
return redirect()->route('keranjang.index')
->with('error', 'Anda tidak memiliki izin untuk menghapus item ini');
}
// Simpan informasi untuk log
$id = $keranjang->id;
$userId = $keranjang->user_id;
// Hapus item dari keranjang
$result = $keranjang->delete();
// Log untuk debugging
\Log::info('Keranjang dihapus: ID=' . $id .
', User=' . $userId .
', Route=' . $request->route()->getName() .
', Method=' . $request->method() .
', Hasil=' . ($result ? 'Sukses' : 'Gagal'));
// Handle jika ini adalah iframe request
if ($request->has('is_js_request') || $request->has('_ts')) {
// Kembalikan HTML minimal untuk iframe
return response('<html><body><script>parent.postMessage("delete_success", "*");</script></body></html>');
}
// Jika ini adalah request AJAX
if ($request->ajax()) {
return response()->json(['success' => true, 'message' => 'Item berhasil dihapus']);
}
return redirect()->route('keranjang.index')
->with('success', 'Item berhasil dihapus dari keranjang');
} catch (\Exception $e) {
\Log::error('Error saat menghapus keranjang: ' . $e->getMessage());
// Handle jika ini adalah iframe request
if ($request->has('is_js_request') || $request->has('_ts')) {
// Kembalikan HTML minimal untuk iframe dengan pesan error
return response('<html><body><script>parent.postMessage("delete_error", "*");</script></body></html>');
}
// Jika ini adalah request AJAX
if ($request->ajax()) {
return response()->json(['success' => false, 'message' => 'Gagal menghapus item: ' . $e->getMessage()], 500);
}
return redirect()->route('keranjang.index')
->with('error', 'Gagal menghapus item: ' . $e->getMessage());
}
}
/**
* Kosongkan keranjang
*/
public function kosongkan()
{
Keranjang::where('user_id', Auth::id())->delete();
return redirect()->route('keranjang.index')
->with('success', 'Keranjang berhasil dikosongkan');
}
/**
* Checkout semua item di keranjang
*/
public function checkout(Request $request)
{
// Jika ada parameter selected_items, gunakan itu (bisa dari GET)
if ($request->has('selected_items')) {
return $this->checkoutSelected($request);
}
// Jika tidak ada parameter, cek session untuk item terpilih
if (session()->has('selected_keranjang_items')) {
$selectedIds = session('selected_keranjang_items');
$items = Keranjang::with('barang')
->where('user_id', Auth::id())
->whereIn('id', $selectedIds)
->get();
if ($items->isNotEmpty()) {
$total = $items->sum('total_harga');
$total_weight = $items->sum(function($item) {
return $item->barang->berat * $item->jumlah;
});
return view('keranjang.checkout', compact('items', 'total', 'selectedIds', 'total_weight'));
}
}
// Default: checkout semua item
$items = Keranjang::with('barang')
->where('user_id', Auth::id())
->get();
if ($items->isEmpty()) {
return redirect()->route('keranjang.index')
->with('error', 'Keranjang Anda kosong');
}
$total = $items->sum('total_harga');
$total_weight = $items->sum(function($item) {
return $item->barang->berat * $item->jumlah;
});
return view('keranjang.checkout', compact('items', 'total', 'total_weight'));
}
/**
* Checkout semua item terpilih di keranjang
*/
public function checkoutSelected(Request $request)
{
$request->validate([
'selected_items' => 'required|array',
'selected_items.*' => 'exists:keranjang,id',
'jumlah' => 'nullable|array',
]);
$selectedIds = $request->selected_items;
$items = Keranjang::with('barang')
->where('user_id', Auth::id())
->whereIn('id', $selectedIds)
->get();
if ($items->isEmpty()) {
return redirect()->route('keranjang.index')
->with('error', 'Tidak ada item yang dipilih');
}
// Update jumlah item jika ada perubahan
if ($request->has('jumlah')) {
foreach ($items as $item) {
if (isset($request->jumlah[$item->id]) && $request->jumlah[$item->id] != $item->jumlah) {
// Validasi stok
if ($request->jumlah[$item->id] > $item->barang->stok) {
return redirect()->route('keranjang.index')
->with('error', 'Jumlah ' . $item->barang->nama_barang . ' melebihi stok yang tersedia');
}
// Update jumlah dan total harga
$item->jumlah = $request->jumlah[$item->id];
$item->total_harga = $item->barang->harga * $item->jumlah;
$item->save();
}
}
}
$total = $items->sum('total_harga');
$total_weight = $items->sum(function($item) {
return $item->barang->berat * $item->jumlah;
});
return view('keranjang.checkout', compact('items', 'total', 'selectedIds', 'total_weight'));
}
/**
* Hapus item terpilih dari keranjang
*/
public function hapusSelected(Request $request)
{
$request->validate([
'selected_items' => 'required|array',
'selected_items.*' => 'exists:keranjang,id',
]);
$count = Keranjang::where('user_id', Auth::id())
->whereIn('id', $request->selected_items)
->delete();
return redirect()->route('keranjang.index')
->with('success', $count . ' item berhasil dihapus dari keranjang');
}
/**
* Hapus item dari keranjang dengan ID manual
*/
public function hapusManual(Request $request)
{
try {
$request->validate([
'id' => 'required|integer|exists:keranjang,id',
]);
$id = $request->input('id');
// Ambil keranjang berdasarkan ID dan user_id
$keranjang = Keranjang::where('id', $id)
->where('user_id', Auth::id())
->first();
if (!$keranjang) {
\Log::warning('Akses tidak sah: User '.Auth::id().' mencoba menghapus keranjang '.$id.' yang tidak ditemukan atau bukan miliknya');
if ($request->ajax() || $request->has('is_js_request')) {
return response('<html><body><script>parent.postMessage("delete_error", "*");</script></body></html>');
}
return redirect()->route('keranjang.index')
->with('error', 'Item tidak ditemukan atau bukan milik Anda');
}
// Debug logging
\Log::debug('Hapus Manual: ID=' . $keranjang->id .
', Auth::id()=' . Auth::id() .
', keranjang->user_id=' . $keranjang->user_id);
// Hapus item dari keranjang
$result = $keranjang->delete();
// Log untuk debugging
\Log::info('Keranjang dihapus (manual): ID=' . $id .
', User=' . Auth::id() .
', Method=' . $request->method() .
', Hasil=' . ($result ? 'Sukses' : 'Gagal'));
// Handle jika ini adalah iframe request
if ($request->has('is_js_request') || $request->has('_ts')) {
// Kembalikan HTML minimal untuk iframe
return response('<html><body><script>parent.postMessage("delete_success", "*");</script></body></html>');
}
// Jika ini adalah request AJAX
if ($request->ajax()) {
return response()->json(['success' => true, 'message' => 'Item berhasil dihapus']);
}
return redirect()->route('keranjang.index')
->with('success', 'Item berhasil dihapus dari keranjang');
} catch (\Exception $e) {
\Log::error('Error saat menghapus keranjang manual: ' . $e->getMessage());
// Handle jika ini adalah iframe request
if ($request->has('is_js_request') || $request->has('_ts')) {
// Kembalikan HTML minimal untuk iframe dengan pesan error
return response('<html><body><script>parent.postMessage("delete_error", "*");</script></body></html>');
}
// Jika ini adalah request AJAX
if ($request->ajax()) {
return response()->json(['success' => false, 'message' => 'Gagal menghapus item: ' . $e->getMessage()], 500);
}
return redirect()->route('keranjang.index')
->with('error', 'Gagal menghapus item: ' . $e->getMessage());
}
}
/**
* Hapus item dari keranjang secara langsung dengan debugging total
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function hapusDirect(Request $request)
{
// Set header content type untuk memastikan respons JSON yang benar
header('Content-Type: application/json');
try {
\Log::debug('====== DEBUG HAPUS DIRECT MULAI ======');
\Log::debug('User ID dari Auth: ' . Auth::id());
// Tangani semua jenis request (JSON atau form)
if ($request->isJson()) {
$data = $request->json()->all();
\Log::debug('Request adalah JSON: ' . json_encode($data));
} else {
$data = $request->all();
\Log::debug('Request adalah form data: ' . json_encode($data));
}
// Validasi minimal
$id = $data['id'] ?? null;
if (!$id) {
\Log::debug('ID tidak ditemukan dalam request');
return response()->json([
'success' => false,
'message' => 'ID tidak valid'
], 400);
}
\Log::debug('ID keranjang untuk dihapus: ' . $id);
try {
// Hapus item dengan query builder untuk menghindari masalah model binding
$result = \DB::table('keranjang')->where('id', $id)->delete();
\Log::debug('Hasil penghapusan dengan query builder: ' . ($result ? 'BERHASIL' : 'GAGAL'));
} catch (\Exception $dbException) {
\Log::error('Database error: ' . $dbException->getMessage());
return response()->json([
'success' => false,
'message' => 'Database error: ' . $dbException->getMessage(),
'error_type' => 'database_error'
], 500);
}
if ($result) {
\Log::debug('====== DEBUG HAPUS DIRECT SELESAI (SUKSES) ======');
return response()->json([
'success' => true,
'message' => 'Item berhasil dihapus (mode debug)',
'debug_info' => [
'user_id' => Auth::id(),
'item_id' => $id,
'deleted' => true,
'time' => now()->toDateTimeString()
]
]);
}
\Log::debug('====== DEBUG HAPUS DIRECT SELESAI (GAGAL) ======');
return response()->json([
'success' => false,
'message' => 'Gagal menghapus item'
], 404); // Gunakan 404 jika item tidak ditemukan
} catch (\Throwable $e) {
\Log::error('Exception: ' . $e->getMessage());
\Log::error($e->getTraceAsString());
\Log::debug('====== DEBUG HAPUS DIRECT SELESAI (ERROR) ======');
// Kembalikan respons JSON yang valid, meskipun terjadi error
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan: ' . $e->getMessage(),
'error_type' => 'exception'
], 500);
}
}
/**
* Update jumlah item di keranjang secara langsung
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function updateDirect(Request $request)
{
// Set header content type untuk memastikan respons JSON yang benar
header('Content-Type: application/json');
try {
\Log::debug('====== DEBUG UPDATE DIRECT MULAI ======');
\Log::debug('User ID dari Auth: ' . Auth::id());
// Tangani semua jenis request (JSON atau form)
if ($request->isJson()) {
$data = $request->json()->all();
\Log::debug('Request adalah JSON: ' . json_encode($data));
} else {
$data = $request->all();
\Log::debug('Request adalah form data: ' . json_encode($data));
}
// Validasi minimal
$id = $data['id'] ?? null;
$jumlah = $data['jumlah'] ?? null;
if (!$id || !$jumlah) {
\Log::debug('ID atau jumlah tidak ditemukan dalam request');
return response()->json([
'success' => false,
'message' => 'ID atau jumlah tidak valid'
], 400);
}
\Log::debug('ID keranjang: ' . $id . ', jumlah baru: ' . $jumlah);
// Ambil item keranjang
$keranjang = Keranjang::where('id', $id)
->where('user_id', Auth::id())
->first();
if (!$keranjang) {
\Log::debug('Item keranjang tidak ditemukan atau bukan milik user ini');
return response()->json([
'success' => false,
'message' => 'Item tidak ditemukan'
], 404);
}
// Validasi stok
$barang = $keranjang->barang;
if ($jumlah > $barang->stok) {
\Log::debug('Jumlah melebihi stok tersedia: ' . $barang->stok);
return response()->json([
'success' => false,
'message' => 'Jumlah melebihi stok yang tersedia'
], 400);
}
// Update jumlah dan total harga
$keranjang->jumlah = $jumlah;
$keranjang->total_harga = $barang->harga * $jumlah;
$result = $keranjang->save();
\Log::debug('Hasil update: ' . ($result ? 'BERHASIL' : 'GAGAL'));
\Log::debug('====== DEBUG UPDATE DIRECT SELESAI (SUKSES) ======');
return response()->json([
'success' => true,
'message' => 'Jumlah berhasil diperbarui',
'data' => [
'id' => $keranjang->id,
'jumlah' => $keranjang->jumlah,
'total_harga' => $keranjang->total_harga,
'harga_satuan' => $barang->harga
]
]);
} catch (\Throwable $e) {
\Log::error('Exception: ' . $e->getMessage());
\Log::error($e->getTraceAsString());
\Log::debug('====== DEBUG UPDATE DIRECT SELESAI (ERROR) ======');
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan: ' . $e->getMessage(),
'error_type' => 'exception'
], 500);
}
}
/**
* Update jumlah item di keranjang dengan form tradisional (fallback)
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function updateFallback(Request $request)
{
try {
\Log::debug('====== UPDATE FALLBACK ======');
\Log::debug('User ID: ' . Auth::id());
\Log::debug('Request data: ' . json_encode($request->all()));
// Validasi minimal
$request->validate([
'id' => 'required|integer|exists:keranjang,id',
'jumlah' => 'required|integer|min:1',
]);
// Ambil item keranjang
$keranjang = Keranjang::where('id', $request->id)
->where('user_id', Auth::id())
->first();
if (!$keranjang) {
\Log::debug('Item keranjang tidak ditemukan atau bukan milik user ini');
return redirect()->route('keranjang.index')
->with('error', 'Item tidak ditemukan');
}
// Validasi stok
$barang = $keranjang->barang;
if ($request->jumlah > $barang->stok) {
\Log::debug('Jumlah melebihi stok tersedia: ' . $barang->stok);
return redirect()->route('keranjang.index')
->with('error', 'Jumlah melebihi stok yang tersedia');
}
// Update jumlah dan total harga
$keranjang->jumlah = $request->jumlah;
$keranjang->total_harga = $barang->harga * $request->jumlah;
$result = $keranjang->save();
\Log::debug('Hasil update: ' . ($result ? 'BERHASIL' : 'GAGAL'));
return redirect()->route('keranjang.index')
->with('success', 'Jumlah berhasil diperbarui');
} catch (\Throwable $e) {
\Log::error('Exception: ' . $e->getMessage());
\Log::error($e->getTraceAsString());
return redirect()->route('keranjang.index')
->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
}
}
}