orderBy('created_at', 'desc') ->paginate(15); return view('sales.index', compact('sales')); } public function create() { // Traemos productos con stock y clientes para los selectores $products = Product::where('stock_quantity', '>', 0)->get(); $clients = Client::orderBy('name')->get(); return view('sales.create', compact('products', 'clients')); } public function store(Request $request) { // Validación estricta $request->validate([ 'client_id' => 'nullable|exists:clients,id', 'payment_method' => 'required|string', 'items' => 'required|array', 'items.*.product_id' => 'required|exists:products,id', 'items.*.quantity' => 'required|integer|min:1', ]); try { // Variable para guardar el objeto venta y usarlo fuera del closure $sale = DB::transaction(function () use ($request) { $totalSale = 0; foreach ($request->items as $item) { $product = Product::find($item['product_id']); $totalSale += $product->price * $item['quantity']; if ($product->stock_quantity < $item['quantity']) { throw new \Exception("No hay suficiente stock de " . $product->name); } } //cabecera $newSale = Sale::create([ //'user_id' => auth()->id(), //empleado logueado 'client_id' => $request->client_id, 'total' => $totalSale, 'payment_method' => $request->payment_method, ]); // 3. Guardar Detalle y Restar Stock foreach ($request->items as $itemData) { $product = Product::findOrFail($itemData['product_id']); SaleDetail::create([ 'sale_id' => $newSale->id, 'product_id' => $product->id, 'quantity' => $itemData['quantity'], 'price' => $product->price, ]); $product->decrement('stock_quantity', $itemData['quantity']); } return $newSale; // Retornamos la venta creada fuera de la transacción }); // 4. REDIRECCIÓN AL DETALLE return redirect()->route('sales.show', $sale)->with('success', '¡Venta registrada exitosamente!'); } catch (\Exception $e) { return back()->with('error', $e->getMessage())->withInput(); } } /** * Muestra el detalle de una venta específica. */ public function show(Sale $sale) { // Cargamos la venta con el cliente y los detalles $sale->load(['client', 'details.product']); return view('sales.show', compact('sale')); } }