ldc-boutique-cnc/app/Http/Controllers/Bo/OrderController.php

541 lines
18 KiB
PHP
Raw Normal View History

2020-11-17 13:41:31 +01:00
<?php
namespace App\Http\Controllers\Bo;
use App\Enums\Order\ValidationStatus;
2020-11-17 13:41:31 +01:00
use App\Http\Controllers\Controller;
use App\Models\Order;
2021-03-27 20:55:16 +01:00
use App\Models\OrderLine;
2020-11-17 13:41:31 +01:00
use App\Models\OrdersProducts;
use App\Models\Product;
2021-03-29 15:10:07 +02:00
use App\Models\Timeslot;
2022-10-03 17:13:44 +02:00
use App\Models\Shop;
use App\Http\Requests\SortOrders;
2021-03-29 15:10:07 +02:00
use Illuminate\Support\Facades\Mail;
2021-04-14 10:39:20 +02:00
use App\Mail\OrderStatusMail;
2021-03-29 15:10:07 +02:00
use App\Mail\OrderConfirmMail;
2021-06-01 10:58:20 +02:00
use App\Mail\OrderConfirmAdminMail;
use App\Jobs\CsvOrderWrite;
use App\Models\Customer;
use App\Models\Setting;
2021-03-27 20:55:16 +01:00
use Carbon\Carbon;
2021-03-29 15:10:07 +02:00
use Carbon\CarbonImmutable;
use Carbon\CarbonInterval;
2021-03-27 20:55:16 +01:00
use Gloudemans\Shoppingcart\Facades\Cart;
use Illuminate\Support\Facades\Auth;
2021-03-29 15:10:07 +02:00
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
2020-11-17 13:41:31 +01:00
2022-10-03 17:13:44 +02:00
class OrderController extends Controller
2020-11-17 13:41:31 +01:00
{
2021-04-14 09:34:23 +02:00
/**
2022-09-03 16:56:16 +02:00
* Display a listing of the resource.
*
2022-10-03 17:13:44 +02:00
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
2021-04-14 09:34:23 +02:00
*/
2022-10-03 17:13:44 +02:00
public function index(Request $request)
{
2022-10-03 17:13:44 +02:00
/** @var \Illuminate\Database\Eloquent\Builder $orders */
$orders = Order::query();
if ($request->search) {
$this->searchQuery(
$orders,
$request->search,
null,
'label'
);
}
2022-10-03 17:13:44 +02:00
// if (Session::has('orders.sort_col') and Session::has('orders.sort_way')) {
// switch (Session::get('orders.sort_col')) {
// case 'date':
// $orders = $orders->orderBy('date', Session::get('orders.sort_way'));
// break;
// case 'status_id':
// $orders = $orders->orderBy('status_id', Session::get('orders.sort_way'));
// break;
// case 'magasin_id':
// $orders = $orders->select('orders.*');
// $orders = $orders->leftJoin('timeslots', 'timeslots.order_id', '=', 'orders.id');
// $orders = $orders->leftJoin('shops', 'timeslots.shop_id', '=', 'shops.id');
// $orders = $orders->orderBy('shops.id', Session::get('orders.sort_way'));
// break;
// case 'date_retrait':
// $orders = $orders->select('orders.*');
// $orders = $orders->leftJoin('timeslots', 'timeslots.order_id', '=', 'orders.id');
// $orders = $orders->orderBy('timeslots.day', Session::get('orders.sort_way'));
// $orders = $orders->orderBy('timeslots.time', Session::get('orders.sort_way'));
// break;
// case 'customer_id':
// $orders = $orders->orderBy('customer_id', Session::get('orders.sort_way'));
// break;
// }//end switch
// }//end if
$this->sortQuery($orders);
$searchFields = trans('Label');
$orders->orderBy('updated_at', 'DESC');
$orders = $orders->paginate(10);
2022-10-03 17:13:44 +02:00
return view('back.orders.index', compact('orders', 'searchFields'));
}
/**
* Met a jour le statut de validation d'une commande en annulé
*
* @param \App\Models\Order $order
* @return \Illuminate\Http\RedirectResponse
*/
public function cancelOrder(Order $order)
{
$order->validation_status = ValidationStatus::cancelled();
$order->saveOrFail();
return back()->with('success', "La commande {$order->reference} a été annulée.");
}
/**
* bo : page détail commande
*
* @param \App\Models\Order $order
* @return \Illuminate\Contracts\View\View
*/
public function orderDetails(Order $order)
{
return view('back.orders.details', [
'orderModel' => $order
]);
2020-11-17 13:41:31 +01:00
}
2022-10-03 17:13:44 +02:00
2022-09-03 16:56:16 +02:00
/**
* orders that ship today
*
* @param SortOrders $request
* @return \Illuminate\Contracts\View\View
*/
public function today(SortOrders $request)
{
$orders = $this->filterOrders($request);
2022-09-03 16:56:16 +02:00
// Filter today.
$today = CarbonImmutable::now()->startOfDay();
$orders = $orders->whereHas('timeslot', function ($q) use ($today) {
$q->where('day', '=', $today->format('d/m/Y'));
});
2022-08-25 12:26:43 +02:00
$orders = $orders->get();
2022-10-03 17:13:44 +02:00
return view('back.orders.index', compact('orders', 'today'));
}
2021-04-14 09:34:23 +02:00
/**
* action de changement de statut vers l'avant
* envoi de mails transctionnels
2022-09-03 16:56:16 +02:00
*
* @param string $reference Reference de la commande.
* @return \Illuminate\Http\RedirectResponse
2021-04-14 09:34:23 +02:00
*/
2022-09-03 16:56:16 +02:00
public function changeStatus(string $reference)
{
$order = Order::where('reference', $reference)->first();
2020-11-17 13:41:31 +01:00
$order->status_id = $order->status_id + 1;
$order->save();
2022-09-03 16:56:16 +02:00
// Send confirm mail.
2021-04-14 10:39:20 +02:00
Mail::to($order->customer->email)->send(new OrderStatusMail($order));
2021-04-13 18:45:36 +02:00
return back()->with('success', "Changement de status enregistré pour la commande " . $order->reference . ".");
2020-11-17 13:41:31 +01:00
}
2021-03-27 20:55:16 +01:00
/**
2021-04-14 09:34:23 +02:00
* front
2021-03-27 20:55:16 +01:00
* Storing order from sales tunnel
2022-09-03 16:56:16 +02:00
*
* @return \Illuminate\Http\RedirectResponse
2021-03-27 20:55:16 +01:00
*/
public function store()
{
2022-09-03 16:56:16 +02:00
// Save.
2021-07-22 16:22:45 +02:00
Cart::instance('panier');
$order = new Order();
2022-09-03 16:56:16 +02:00
// Generate order ref.
2021-07-21 17:10:11 +02:00
$order->reference = $this->generateOrderRef();
2021-03-29 15:10:07 +02:00
$order->date = Carbon::now();
$order->status_id = 1;
$order->total = str_replace(',', '.', str_replace(' ', '', Cart::total()));
2021-03-27 20:55:16 +01:00
$order->customer_id = Auth::user()->id;
$order->save();
2022-09-03 16:56:16 +02:00
// Order_id.
2021-07-21 17:10:11 +02:00
Cart::instance('panier');
2021-03-27 20:55:16 +01:00
$cart = Cart::content();
2021-03-29 15:10:07 +02:00
foreach ($cart as $cartItem) {
$order_line = new OrderLine();
$order_line->order_id = $order->id;
2021-03-27 20:55:16 +01:00
$order_line->product_id = $cartItem->model->id;
$order_line->quantity = $cartItem->qty;
2022-09-03 16:56:16 +02:00
// Gross unit price.
$order_line->unit_price = $cartItem->model->priceHt;
2022-09-03 16:56:16 +02:00
// Discount per unit.
$order_line->unit_discount = $cartItem->model->discountAmount;
2022-09-03 16:56:16 +02:00
// Tax rate for this line.
2021-03-27 20:55:16 +01:00
$order_line->tax_rate = $cartItem->taxRate;
2022-09-03 16:56:16 +02:00
// 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.
2021-03-27 20:55:16 +01:00
$order_line->total_discount = $order_line->unit_discount * $order_line->quantity;
2022-09-03 16:56:16 +02:00
// Gross amount for the line.
$order_line->total_ht = ($order_line->unit_price - $order_line->unit_discount) * $order_line->quantity;
2022-09-03 16:56:16 +02:00
// Tax amount for the line.
2021-03-27 20:55:16 +01:00
$order_line->total_tax = $order_line->unit_tax * $order_line->quantity;
2022-09-03 16:56:16 +02:00
// Total TTC avec remises de la ligne.
2021-03-27 20:55:16 +01:00
$order_line->total_ttc = $order_line->total_ht + $order_line->total_tax;
2021-03-27 20:55:16 +01:00
$order_line->save();
2022-10-03 17:13:44 +02:00
} //end foreach
2021-03-27 20:55:16 +01:00
2022-09-03 16:56:16 +02:00
// Empty cart.
2021-03-27 20:55:16 +01:00
Cart::destroy();
2022-09-03 16:56:16 +02:00
// Then redirect.
return redirect()->route('order-tunnel.pick-slot', ['reference' => $order->reference]);
2021-03-27 20:55:16 +01:00
}
2021-07-21 17:10:11 +02:00
/**
* generate order Reference
* for a new order
2022-09-03 16:56:16 +02:00
*
* @return string
2021-07-21 17:10:11 +02:00
*/
public function generateOrderRef()
{
2021-07-21 17:10:11 +02:00
2022-09-03 16:56:16 +02:00
// Format : YYYYMMDDHHMM000.
2021-07-21 17:10:11 +02:00
$now = Carbon::now();
2022-09-03 16:56:16 +02:00
// Count todays orders.
2021-07-21 17:10:11 +02:00
$countorders = Order::whereDate('created_at', Carbon::today())->count();
2022-09-03 16:56:16 +02:00
// Add one.
2021-07-21 17:10:11 +02:00
$countorders++;
$ref = $now->isoFormat('YYYYMMDDHHmm') . str_pad($countorders, 3, "0", STR_PAD_LEFT);
2021-07-21 17:10:11 +02:00
return $ref;
}
2021-04-14 09:34:23 +02:00
/**
* front tunnel de commande étape 3 : choix de créneau
2022-09-03 16:56:16 +02:00
*
* @param string $reference
* @return \Illuminate\Contracts\View\View
2021-04-14 09:34:23 +02:00
*/
2022-09-03 16:56:16 +02:00
public function timeSlotPick(string $reference)
2021-03-27 20:55:16 +01:00
{
$activestep = 3;
if (config('theme.multi_relay')) {
2022-10-03 17:13:44 +02:00
$shop = Shop::all();
} else {
2022-10-03 17:13:44 +02:00
$shop = Shop::first();
}
$availCreneaux = array();
2022-09-03 16:56:16 +02:00
$order = Order::where('reference', '=', $reference)->firstOrFail();
2022-10-03 17:13:44 +02:00
return view('sales.pick-slot', compact('activestep', 'availCreneaux', 'order', 'shop'));
}
/**
* add timeslot by interval between start and end hour
*
* @param array $plage
* @param integer $weekDay
* @param CarbonImmutable $current
2022-10-03 17:13:44 +02:00
* @param Shop $shop
* @param CarbonImmutable $now
* @param CarbonImmutable $today
* @param CarbonInterval $delaiPrepa
* @param CarbonInterval $interval
* @param Carbon $currentTime
* @param Carbon $endTime
* @return array
*/
private function addCreneaux(
array $plage,
int $weekDay,
CarbonImmutable $current,
2022-10-03 17:13:44 +02:00
Shop $shop,
CarbonImmutable $now,
CarbonImmutable $today,
CarbonInterval $delaiPrepa,
CarbonInterval $interval,
Carbon $currentTime,
Carbon $endTime
) {
$retArray = array();
do {
$creneau = $currentTime->format('H:i');
2022-10-03 17:13:44 +02:00
$nbtakens = $shop->timeslots()
->where('day', $current->format('d/m/Y'))
->where('time', $creneau)->count();
if ($nbtakens >= $plage[$weekDay]['max_orders_per_interval']) {
$isDispo = false;
} else {
$isDispo = true;
}
if (
$current->addHours($currentTime->format('H'))->addMinutes($currentTime->format('i')) <
$now->add($delaiPrepa)
) {
$isDispo = false;
}
// Attention si la date est passée (today mais avant maintenant) : pas de créneau.
if ($current > $today || $currentTime >= $now) {
$retArray[] = array($creneau, $isDispo);
}
$currentTime->add($interval);
} while ($currentTime <= $endTime);
return $retArray;
}
/**
2022-09-03 16:56:16 +02:00
* give array of available crenaux
*
* @param integer $id
* @return array
*/
2022-09-03 16:56:16 +02:00
public function getAvailableCreneauxByShop(int $id)
{
2022-09-03 16:56:16 +02:00
// Setting à stocker et réutiliser.
$plage_days = Setting::where('key', 'order_withdrawal_period')->firstOrFail()->value;
2021-03-29 15:10:07 +02:00
2022-10-03 17:13:44 +02:00
$shop = Shop::findOrFail($id);
$timeslotSettings = $shop->timeslotSettings;
2022-08-25 12:26:43 +02:00
// $timeslotSettings = TimeslotSetting::all();
2022-09-03 16:56:16 +02:00
// Fabriquons un tableau recap.
$plage = array();
foreach ($timeslotSettings as $day) {
$plage[$day->day_index] = array(
'morning_start' => $day->morning_start,
'morning_end' => $day->morning_end,
'afternoon_start' => $day->afternoon_start,
'afternoon_end' => $day->afternoon_end,
'interval' => $day->interval,
'min_order_preparation' => $day->min_order_preparation,
'max_orders_per_interval' => $day->max_orders_per_interval
);
}
2022-09-03 16:56:16 +02:00
// Génération des plages.
// Start today.
$today = CarbonImmutable::now()->startOfDay();
$weekDay = $today->weekday();
2022-09-03 16:56:16 +02:00
// Final boundary (permet de limiter la liste des jours d'exception).
2021-04-21 16:48:37 +02:00
$finalday = $today->add($plage_days, 'day');
$now = CarbonImmutable::now();
2022-09-03 16:56:16 +02:00
// Jours exceptions.
2022-10-03 17:13:44 +02:00
$noCollectDays = $shop->collectionExceptions()
->whereDate('date', '>', $now)
->whereDate('date', '<=', $finalday)
->orderBy('date')->get();
$delaiPrepa = CarbonInterval::createFromFormat('h:i', $plage[$weekDay]['min_order_preparation'] ?? '01:00');
2021-03-29 15:10:07 +02:00
$availCreneaux = array();
for ($i = 0; $i < $plage_days; $i++) {
$current = $today->add($i, 'day');
$weekDay = $current->weekday();
$interval = CarbonInterval::createFromFormat('h:i', $plage[$weekDay]['interval'] ?? '00:15');
2022-09-03 16:56:16 +02:00
// Si c'est un jour exception skip.
2021-04-21 16:48:37 +02:00
$skip = false;
foreach ($noCollectDays as $not_today) {
if ($current->isSameDay($not_today->date)) {
2021-04-21 16:48:37 +02:00
$skip = true;
}
}
if ($skip) {
2021-04-21 16:48:37 +02:00
continue;
}
$availCreneaux[$current->format('d/m/Y')] = array();
2022-09-03 16:56:16 +02:00
// Matinée.
if (!empty($plage[$weekDay]['morning_start'])) {
$currentTime = Carbon::createFromTimeString($plage[$weekDay]['morning_start']);
$endTime = Carbon::createFromTimeString($plage[$weekDay]['morning_end']);
$morningCreneaux = $this->addCreneaux(
$plage,
$weekDay,
$current,
2022-10-03 17:13:44 +02:00
$shop,
$now,
$today,
$delaiPrepa,
$interval,
$currentTime,
$endTime
);
$availCreneaux[$current->format('d/m/Y')] = array_merge(
$availCreneaux[$current->format('d/m/Y')],
$morningCreneaux
);
} //end if
2022-09-03 16:56:16 +02:00
// Aprem.
if (!empty($plage[$weekDay]['afternoon_start'])) {
$currentTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_start']);
$endTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_end']);
$afternoonCreneaux = $this->addCreneaux(
$plage,
$weekDay,
$current,
2022-10-03 17:13:44 +02:00
$shop,
$now,
$today,
$delaiPrepa,
$interval,
$currentTime,
$endTime
);
$availCreneaux[$current->format('d/m/Y')] = array_merge(
$availCreneaux[$current->format('d/m/Y')],
$afternoonCreneaux
);
} //end if
2022-10-03 17:13:44 +02:00
} //end for
return $availCreneaux;
}
2022-09-03 16:56:16 +02:00
/**
* Call ajax pour le composant vue de timeslots.
*
* @param Request $request
* @return array
*/
public function getAvailableCreneaux(Request $request)
{
return $this->getAvailableCreneauxByShop($request->id);
2021-03-27 20:55:16 +01:00
}
2021-04-14 09:34:23 +02:00
/**
* front
* enregistrement du créneau de collect
* et validation de la commande
2022-09-03 16:56:16 +02:00
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
2021-04-14 09:34:23 +02:00
*/
2021-03-29 15:10:07 +02:00
public function setTimeSlot(Request $request)
2021-03-27 20:55:16 +01:00
{
$request->validate([
'selectedmagasin' => 'required',
'selectedcreneau' => 'required',
'ok_cgv' => 'accepted',
]);
$time_slot = Carbon::createFromFormat('d/m/Y-H:i', $request->selectedcreneau);
$tsday = explode('-', $request->selectedcreneau)[0];
$tstime = explode('-', $request->selectedcreneau)[1];
$magasin_id = $request->selectedmagasin;
$reference = $request->order_ref;
$order = Order::where('reference', '=', $reference)->firstOrFail();
2021-03-29 15:10:07 +02:00
if ($order->status_id == 1) {
2022-09-03 16:56:16 +02:00
// On ne traite l'enregistrement que pour les commandes en attente venant de l'étape de récap.
// Save timeslot.
$timeslot = Timeslot::firstOrNew(['order_id' => $order->id]);
$timeslot->order_id = $order->id;
$timeslot->magasin_id = $magasin_id;
$timeslot->day = $tsday;
$timeslot->time = $tstime;
2021-03-29 15:10:07 +02:00
$timeslot->save();
2022-09-03 16:56:16 +02:00
// Save order status.
$order->status_id = 3;
2021-03-29 15:10:07 +02:00
$order->save();
2022-09-03 16:56:16 +02:00
// Send confirm mail.
Mail::to($order->customer->email)->queue(new OrderConfirmMail($order));
2022-09-03 16:56:16 +02:00
// Envoi du mail de confirmation aux admins site.
$toMailSetting = Setting::where('key', 'send_order_confirm_mail_to')->first();
if (empty($toMailSetting->value)) {
$toMail = config('mail.from.address');
} else {
$toMail = $toMailSetting->value;
}
Mail::to($toMail)->queue(new OrderConfirmAdminMail($order));
2022-10-03 17:13:44 +02:00
} //end if
2021-03-29 15:10:07 +02:00
2022-09-03 16:56:16 +02:00
// Redirect to final confirmation.
return redirect()->route('order-tunnel.confirm', ['reference' => $order->reference]);
2021-03-27 20:55:16 +01:00
}
2022-09-03 16:56:16 +02:00
/**
* generate Order
* Test method
*
* @param string $reference
* @return void
*/
public function generateOrder(string $reference)
{
$order = Order::where('reference', '=', $reference)->with('lines')->firstOrFail();
$job = new CsvOrderWrite($order);
$job->handle();
dd('end');
}
2021-04-14 09:34:23 +02:00
/**
* front
* page de confirmation de commande
2022-09-03 16:56:16 +02:00
*
* @param string $reference
* @return \Illuminate\Contracts\View\View
2021-04-14 09:34:23 +02:00
*/
2022-09-03 16:56:16 +02:00
public function confirmOrder(string $reference)
2021-03-27 20:55:16 +01:00
{
$activestep = 4;
2021-03-29 15:10:07 +02:00
$idcommande = Session::get('idcommande');
$order = Order::where('reference', '=', $reference)->firstOrFail();
2021-03-29 15:10:07 +02:00
2022-08-25 12:26:43 +02:00
// 1 seul magasin en base pour le moment
2022-10-03 17:13:44 +02:00
$shop = Shop::find($order->timeslot->shop->id);
2021-04-21 17:50:57 +02:00
2022-10-03 17:13:44 +02:00
return view('sales.confirm', compact('activestep', 'order', 'shop'));
2021-03-27 20:55:16 +01:00
}
2021-04-13 17:21:39 +02:00
2021-04-14 09:34:23 +02:00
/**
* bo
* ajx : affichage d'infos sur un client
2022-09-03 16:56:16 +02:00
*
* @param integer $id
* @param string|null $mode
* @return \Illuminate\Contracts\View\View
2021-04-14 09:34:23 +02:00
*/
2022-09-03 16:56:16 +02:00
public function getCustomerInfo(int $id, string $mode = null)
{
$cust = Customer::findOrFail($id);
if (!is_null($mode)) {
if ($mode == "tippy") {
2022-10-03 17:13:44 +02:00
return view('back.customer.tippy-card', compact('cust'));
}
if ($mode == "json") {
return $cust->apiData;
}
2022-10-03 17:13:44 +02:00
return view('back.customer.info-card', compact('cust'));
}
2022-10-03 17:13:44 +02:00
return view('back.customer.info-popup', compact('cust'));
2021-04-13 17:21:39 +02:00
}
2020-11-17 13:41:31 +01:00
}