ldc-boutique-cnc/app/Http/Controllers/Fo/OrderController.php
2022-12-05 17:51:18 +01:00

234 lines
7.9 KiB
PHP

<?php
namespace App\Http\Controllers\Fo;
use App\Enums\Order\DeliveryStatus;
use App\Enums\Order\OrderProcess;
use App\Enums\Order\PaymentStatus;
use App\Enums\Order\ValidationStatus;
use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\Orders\ShippingModeFormRequest;
use App\Models\DeliveryMode;
use App\Models\Order;
use Carbon\Carbon;
use Gloudemans\Shoppingcart\Facades\Cart;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\ValidationException;
class OrderController extends Controller
{
// * --- TUNNEL DE COMMANDE ---
/**
* Récapitualtif du panier
*
* @return \Illuminate\Contracts\View\View
*/
public function basketRecap()
{
// * On peut passer commande ?
$this->authorize('orderThings', Order::class);
$this->assertDoesNotHaveEmptyBasket();
$this->setOrderProcessStep(OrderProcess::reviewBasket());
/** @var \Gloudemans\Shoppingcart\Cart */
$basket = app('basket');
$messages = [];
$basket = $this->filterBasketKeepOnlyOrderableItems($basket, $messages);
if (!empty($messages)) {
Session::flash('warning', \collect($messages)->implode(",\n"));
}
$basketItems = $this->basketToList($basket);
return view('front.order-tunnel.basket-recap', compact(
'basket',
'basketItems'
));
}
/**
* Select shipping Mode And create Session Order
*
* @return \Illuminate\Contracts\View\View
*/
public function shippingMode()
{
// * On peut passer commande ?
$this->authorize('orderThings', Order::class);
$this->assertDoesNotHaveEmptyBasket();
$this->setOrderProcessStep(OrderProcess::shippingMethod(), OrderProcess::reviewBasket());
// * CREATE ORDER
/** @var \App\Models\Customer $customer */
$customer = auth('frontend')->user();
/** @var \Gloudemans\Shoppingcart\Cart */
$basket = app('basket');
/** @var \App\Models\Order|null $order */
$order = Order::getCurrentOrder();
// * If there was a previous order that was not ended use the ID.
/** @var \App\Models\Order */
$order = $order ?? new Order();
$order->delivery_status = DeliveryStatus::pending();
$order->payment_status = PaymentStatus::pending();
$order->validation_status = ValidationStatus::pending();
$order->assignBasket($basket);
$order->customer()->associate($customer);
// * Save Session Order
Session::put('currentOrder', $order);
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\DeliveryMode> */
$deliveryModes = app('DeliveryModesGlobal');
return view('front.order-tunnel.shipping-mode', \compact('deliveryModes'));
}
/**
* Save shipping Mode
*
* @param \App\Http\Requests\Fo\Orders\ShippingModeFormRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function shippingModeSubmit(ShippingModeFormRequest $request)
{
$this->assertDoesNotHaveEmptyBasket();
$this->setOrderProcessStep(OrderProcess::shippingMethod());
/** @var \App\Models\DeliveryMode $mode */
if (!($mode = DeliveryMode::availables()->whereId($request->mode)->first())) {
$e = new \RuntimeException('Mode de livraison non disponible', 1);
report($e);
Session::flash('error', trans('Mode de livraison non disponible'));
return \back()->withException($e);
}
/** @var \App\Models\Order $order */
$order = Order::getCurrentOrder();
$order->deliveryMode()->associate($mode);
Session::put('currentOrder', $order);
return \response()->redirectToRoute('orders.shipping');
}
// * --- FIN TUNNEL DE COMMANDE ---
/**
* front
* Storing order from sales tunnel
*
* @return \Illuminate\Http\RedirectResponse
*/
public function basketRecapSubmit()
{
// Save.
Cart::instance('panier');
$order = new Order();
// Generate order ref.
$order->reference = $this->generateOrderRef();
$order->date = Carbon::now();
$order->status_id = 1;
$order->total = str_replace(',', '.', str_replace(' ', '', Cart::total()));
$order->customer_id = Auth::user()->id;
$order->save();
// Order_id.
Cart::instance('panier');
$cart = Cart::content();
foreach ($cart as $cartItem) {
$order_line = new OrderLine();
$order_line->order_id = $order->id;
$order_line->product_id = $cartItem->model->id;
$order_line->quantity = $cartItem->qty;
// Gross unit price.
$order_line->unit_price = $cartItem->model->priceHt;
// Discount per unit.
$order_line->unit_discount = $cartItem->model->discountAmount;
// Tax rate for this line.
$order_line->tax_rate = $cartItem->taxRate;
// Tax amount par unit.
$order_line->unit_tax = round(
(($order_line->unit_price - $order_line->unit_discount) * ($order_line->tax_rate / 100)) * 100
) / 100;
// Discount amount for the line.
$order_line->total_discount = $order_line->unit_discount * $order_line->quantity;
// Gross amount for the line.
$order_line->total_ht = ($order_line->unit_price - $order_line->unit_discount) * $order_line->quantity;
// Tax amount for the line.
$order_line->total_tax = $order_line->unit_tax * $order_line->quantity;
// Total TTC avec remises de la ligne.
$order_line->total_ttc = $order_line->total_ht + $order_line->total_tax;
$order_line->save();
} //end foreach
// Empty cart.
Cart::destroy();
// Then redirect.
return redirect()->route('order-tunnel.pick-slot', ['reference' => $order->reference]);
}
/**
* Assert user does not have an empty basket
* or redirect with warning
*
* @return void
*/
private function assertDoesNotHaveEmptyBasket(): void
{
/** @var \Gloudemans\Shoppingcart\Cart */
$basket = app('basket');
if (!$basket->count()) {
\redirect()->route('home')
->with('warning', trans('Vous n\'avez aucun produit dans votre panier'))
->throwResponse();
}
}
/**
* Validate Process step
*
* @param \App\Enums\Order\OrderProcess $step
* @param \App\Enums\Order\OrderProcess|null $assertDid
* @return void
* @throws \Illuminate\Validation\ValidationException If previous was not done.
*/
private function setOrderProcessStep(OrderProcess $step, OrderProcess $assertDid = null): void
{
if ($assertDid) {
if (!Session::get('PreviousOrderStep')) {
Session::put('PreviousOrderStep', collect());
}
/** @var \Illuminate\Support\Collection */
$previousSteps = Session::get('PreviousOrderStep');
if (Session::get('OrderStep') < $step) {
/** @var \App\Enums\OrderProcess */
$previousStep = Session::get('OrderStep');
$previousSteps->put($previousStep->value, $previousStep);
Session::put('PreviousOrderStep', $previousSteps);
}
if (!$previousSteps->count()) {
\redirect()->route('home')
->with('warning', trans('Vous devez d\'abord valider votre panier'))
->throwResponse();
}
if (!$previousSteps->contains($assertDid)) {
throw ValidationException::withMessages(['Étape précédente requise']);
}
} //end if
Session::put('OrderStep', $step);
}
}