latest()->paginate(20); return response()->json($purchases); } /** * Store a new purchase with items. * * Expected payload: * { * user_id: int, * status: string, * items: [ { wine_id: int, quantity: int, unit_price?: decimal }, ... ] * } */ public function store(Request $request) { $data = $request->validate([ 'user_id' => 'required|integer|exists:users,id', 'status' => 'nullable|string', 'items' => 'required|array|min:1', 'items.*.wine_id' => 'required|integer|exists:wines,wine_id', 'items.*.quantity' => 'required|integer|min:1', 'items.*.unit_price' => 'nullable|numeric|min:0', ]); try { $purchase = Purchase::createWithItems([ 'user_id' => $data['user_id'], 'status' => $data['status'] ?? 'pending', ], $data['items']); return response()->json(['success' => true, 'purchase' => $purchase->load(['items.wine','user'])], 201); } catch (\Exception $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 422); } } /** * Process checkout from shopping cart */ public function checkout(Request $request) { $validated = $request->validate([ 'full_name' => 'required|string|max:255', 'phone' => ['required', 'string', 'max:20', 'regex:/^[\+]?[(]?[0-9]{1,4}[)]?[-\s\.]?[(]?[0-9]{1,4}[)]?[-\s\.]?[0-9]{1,9}$/'], 'country' => 'required|string|max:100', 'street' => 'required|string|max:255', 'city' => 'required|string|max:255', 'postal_code' => ['required', 'string', 'max:20', 'regex:/^[0-9]{3}\s?[0-9]{2}$/'], ], [ 'phone.regex' => 'The phone number format is invalid. Please use format: +420 123 456 789', 'postal_code.regex' => 'The postal code format is invalid. Please use format: 123 45', ]); $cart = Session::get('cart', []); if (empty($cart)) { return redirect()->route('cart.index')->with('error', 'Košík je prázdny.'); } // Prepare items for purchase creation $items = []; foreach ($cart as $wineId => $cartItem) { $wine = Wine::find($wineId); if (!$wine) { continue; } // Check stock if ($wine->bottles_in_stock < $cartItem['quantity']) { return redirect()->route('cart.index') ->with('error', "Nedostatočné množstvo na sklade pre {$wine->wine_name}."); } $items[] = [ 'wine_id' => $wineId, 'quantity' => $cartItem['quantity'], 'unit_price' => $wine->price_per_bottle, ]; } try { // Create purchase with invoice details in note $invoiceNote = "Name: {$validated['full_name']}\n" . "Phone: {$validated['phone']}\n" . "Street: {$validated['street']}\n" . "City: {$validated['city']}\n" . "Postal Code: {$validated['postal_code']}\n" . "Country: {$validated['country']}"; $purchase = Purchase::createWithItems([ 'user_id' => Auth::id(), 'status' => 'completed', 'note' => $invoiceNote, 'purchased_at' => now(), ], $items); // Clear cart after successful purchase Session::forget('cart'); return redirect()->route('purchases.my') ->with('success', 'Objednávka bola úspešne vytvorená!'); } catch (\Exception $e) { return redirect()->route('cart.index') ->with('error', 'Chyba pri vytváraní objednávky: ' . $e->getMessage()); } } /** * Display customer's purchase history */ public function myPurchases() { $purchases = Purchase::with(['items.wine.grapeVariety']) ->where('user_id', Auth::id()) ->orderBy('purchased_at', 'desc') ->orderBy('created_at', 'desc') ->get(); return view('purchases.my', compact('purchases')); } }