This commit is contained in:
174
app/Http/Controllers/Shop/CheckoutController.php
Normal file
174
app/Http/Controllers/Shop/CheckoutController.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Shop;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Order;
|
||||
use App\Models\OrderItem;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class CheckoutController extends Controller
|
||||
{
|
||||
private const CHECKOUT_CUSTOMER_KEY = 'checkout.customer';
|
||||
|
||||
public function show(Request $request)
|
||||
{
|
||||
$items = $this->cartItems($request);
|
||||
|
||||
if ($items->isEmpty()) {
|
||||
return redirect()->route('cart.index')->with('status', 'Корзина пустая. Добавьте товары перед оформлением.');
|
||||
}
|
||||
|
||||
return view('shop.checkout', [
|
||||
'items' => $items,
|
||||
'total' => $items->sum('subtotal'),
|
||||
'itemsCount' => $items->sum('quantity'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function prepare(Request $request)
|
||||
{
|
||||
$items = $this->cartItems($request);
|
||||
|
||||
if ($items->isEmpty()) {
|
||||
return redirect()->route('cart.index')->with('status', 'Корзина пустая. Добавьте товары перед оформлением.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'customer_name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'email', 'max:255'],
|
||||
'phone' => ['nullable', 'string', 'max:50'],
|
||||
'address' => ['required', 'string', 'max:500'],
|
||||
'comment' => ['nullable', 'string', 'max:1000'],
|
||||
]);
|
||||
|
||||
$validated['payment_method'] = 'card_transfer';
|
||||
$request->session()->put(self::CHECKOUT_CUSTOMER_KEY, $validated);
|
||||
|
||||
return redirect()->route('checkout.payment');
|
||||
}
|
||||
|
||||
public function payment(Request $request)
|
||||
{
|
||||
$items = $this->cartItems($request);
|
||||
|
||||
if ($items->isEmpty()) {
|
||||
return redirect()->route('cart.index')->with('status', 'Корзина пустая. Добавьте товары перед оформлением.');
|
||||
}
|
||||
|
||||
$customer = $request->session()->get(self::CHECKOUT_CUSTOMER_KEY);
|
||||
if (!is_array($customer)) {
|
||||
return redirect()->route('checkout.show')->with('status', 'Сначала заполните данные получателя.');
|
||||
}
|
||||
|
||||
return view('shop.checkout-payment', [
|
||||
'items' => $items,
|
||||
'total' => $items->sum('subtotal'),
|
||||
'itemsCount' => $items->sum('quantity'),
|
||||
'customer' => $customer,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$items = $this->cartItems($request);
|
||||
|
||||
if ($items->isEmpty()) {
|
||||
return redirect()->route('cart.index')->with('status', 'Корзина пустая. Добавьте товары перед оформлением.');
|
||||
}
|
||||
|
||||
$validated = $request->session()->get(self::CHECKOUT_CUSTOMER_KEY);
|
||||
if (!is_array($validated)) {
|
||||
return redirect()->route('checkout.show')->with('status', 'Сначала заполните данные получателя.');
|
||||
}
|
||||
|
||||
$validator = validator($validated, [
|
||||
'customer_name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'email', 'max:255'],
|
||||
'phone' => ['nullable', 'string', 'max:50'],
|
||||
'address' => ['required', 'string', 'max:500'],
|
||||
'comment' => ['nullable', 'string', 'max:1000'],
|
||||
'payment_method' => ['required', 'string', Rule::in(['card_transfer'])],
|
||||
]);
|
||||
$validated = $validator->validate();
|
||||
|
||||
$order = DB::transaction(function () use ($request, $items, $validated) {
|
||||
$order = Order::create([
|
||||
'user_id' => optional($request->user())->id,
|
||||
'status' => 'new',
|
||||
'payment_method' => $validated['payment_method'],
|
||||
'total' => $items->sum('subtotal'),
|
||||
'items_count' => $items->sum('quantity'),
|
||||
'customer_name' => $validated['customer_name'],
|
||||
'email' => $validated['email'],
|
||||
'phone' => $validated['phone'] ?? null,
|
||||
'address' => $validated['address'],
|
||||
'comment' => $validated['comment'] ?? null,
|
||||
]);
|
||||
|
||||
$rows = $items->map(function (array $item) use ($order) {
|
||||
return [
|
||||
'order_id' => $order->id,
|
||||
'product_id' => $item['product']->id,
|
||||
'name' => $item['product']->name,
|
||||
'price' => $item['product']->price,
|
||||
'quantity' => $item['quantity'],
|
||||
'subtotal' => $item['subtotal'],
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
})->all();
|
||||
|
||||
OrderItem::insert($rows);
|
||||
|
||||
return $order;
|
||||
});
|
||||
|
||||
$request->session()->forget('cart');
|
||||
$request->session()->forget(self::CHECKOUT_CUSTOMER_KEY);
|
||||
|
||||
return redirect()->route('checkout.success', $order);
|
||||
}
|
||||
|
||||
public function success(Order $order)
|
||||
{
|
||||
return view('shop.checkout-success', [
|
||||
'order' => $order,
|
||||
]);
|
||||
}
|
||||
|
||||
private function cartItems(Request $request)
|
||||
{
|
||||
$cart = (array) $request->session()->get('cart', []);
|
||||
|
||||
$products = Product::query()
|
||||
->whereIn('id', array_keys($cart))
|
||||
->where('is_active', true)
|
||||
->get()
|
||||
->keyBy('id');
|
||||
|
||||
return collect($cart)
|
||||
->map(function ($quantity, $productId) use ($products) {
|
||||
$product = $products->get((int) $productId);
|
||||
if (!$product) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$qty = max(1, min((int) $quantity, (int) $product->stock));
|
||||
if ($qty < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'product' => $product,
|
||||
'quantity' => $qty,
|
||||
'subtotal' => (float) $product->price * $qty,
|
||||
];
|
||||
})
|
||||
->filter()
|
||||
->values();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user