File: D:/HostingSpaces/SBogers10/shop.komma.nl/app/Orders/Kms/OrderController.php
<?php
namespace App\Orders\Kms;
use Illuminate\Support\Facades\Request;
use Illuminate\View\View;
use Komma\KMS\Core\Attributes\Models\Traits\HasThumbnailInterface;
use Komma\KMS\Core\Entities\DisplayNameInterface;
use Komma\KMS\Core\SectionController;
use App\Invoicing\CreditInvoiceService;
use App\Invoicing\InvoiceService;
use App\Orders\CreditInvoiceNumberSequence;
use App\Orders\Models\Order;
use App\Orders\OrderStatus;
use App\Orders\SearchRequest;
use App\Payment\Transaction;
use App\Shipments\ShipmentService;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\MessageBag;
use Komma\KMS\Globalization\RegionInfoInterface;
use Komma\KMS\Helpers\KommaHelpers;
class OrderController extends SectionController
{
protected string $slug = "orders";
/** @var string */
protected string $classModelName = Order::class;
private OrderService $orderService;
private ShipmentService $shipmentService;
private OrderMailService $orderMailService;
private InvoiceService $invoiceService;
private CreditInvoiceService $creditInvoiceService;
private CreditInvoiceNumberSequence $creditInvoiceNumberGenerator;
/**
* Constructor
*/
public function __construct()
{
$orderSection = new OrderSection($this->slug);
$this->orderService = new OrderService();
$this->orderMailService = new OrderMailService();
$this->shipmentService = new ShipmentService();
$this->invoiceService = new InvoiceService();
$this->creditInvoiceService = new CreditInvoiceService();
$this->creditInvoiceNumberGenerator = app(CreditInvoiceNumberSequence::class);
parent::__construct($orderSection);
}
/**
* This method is called on the overview page.
* It will render the section and view.
*
* @return mixed
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function index()
{
$this->authorize('index', $this->classModelName);
$shopRegionInfo = app(RegionInfoInterface::class);
$perpage = request()->get('perpage', 10);
$ordersCollection = Order::with(['latestTransactions'])->paginate($perpage)->appends(['perpage' => $perpage]);
$view = $this->renderOrderIndex();
$view->with('orders', $ordersCollection)
->with('shopRegionInfo', $shopRegionInfo)
->with('perpage', $perpage)
->with('resultsTypeTranslation', __('KMS::orders.search_results'));
return $view;
}
/**
* Search for orders
*
* @param SearchRequest $request
* @return View|\Illuminate\Http\Resources\Json\AnonymousResourceCollection
*/
public function OrderSearch(SearchRequest $request)
{
//Determine how many results per page we need to show, or simply 5 if not specified by the user.
$resultsPerPage = (is_numeric($request->get('perpage')) ? (int) $request->get('perpage') : 10);
//Build an array of search fields to search a given value in;
$searchFields = [
$request->get('search_for') => $request->get('search_value'),
'status' => $request->has('status') && in_array($request->get('status'), OrderStatus::getAsArray()) ? $request->get('status') : 'each'
];
//Search
$ordersCollectionPaginator = $this->orderService->search($searchFields)->orderBy('created_at', 'desc')->paginate($resultsPerPage)->appends(['perpage' => $resultsPerPage]);
$ordersCollectionPaginator->appends($request->all()); //Add existing query string parameters to the current pagination links
//Get the region info for the shop
$shopRegionInfo = app(RegionInfoInterface::class);
//Make the input a user entered, available for the next request.
$request->flash();
//Return to the order index page with the found orders
$view = $this->renderOrderIndex();
return $view->with('orders', $ordersCollectionPaginator)
->with('shopRegionInfo', $shopRegionInfo)
->with('perpage', $resultsPerPage)
->with('status', $request->get('status'))
->with('resultsTypeTranslation', __('KMS::orders.search_results'));
}
/**
* Batch edit orders
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function batchEdit(Request $request)
{
$orderIds = \Request::get('order_ids');
if(!$orderIds) return redirect()->back()->withErrors(['general' => __('KMS::orders.batch.no_orders_selected')]);
//Convert te order ids to integers instead of strings and use them to get the orders we need to batch edit
$orderIds = array_map(function(string $orderId) {
return (int) $orderId;
}, $orderIds);
$orders = Order::with(['customer'])->whereIn('id', $orderIds)->get();
if(Request::has('change_status') && Request::has('change_status_to')) {
$this->orderService->changeOrdersStatus($orders, \Request::get('change_status_to'));
$orders->each(function(Order $order) {
$this->orderMailService->mailCustomerAboutCurrentOrderStatus($order, true);
});
return redirect()->back()->withSuccess(trans_choice('KMS::orders.batch.status_changed', $orders->count(), ['count' => $orders->count(), 'status' => __('KMS::orders.status.'.\Request::get('change_status_to'))]));
}
return redirect()->back()->withErrors(['general' => __('KMS::orders.batch.edit_fail')]);
}
/**
* This method handles the update functionality.
* And is called by the edit form.
* The method is route model binded via the RouteServiceProvider to the user class
*
* @param $idOrModel Order|int
* @return mixed
* @throws \Exception
* @throws \Throwable
*/
public function update($idOrModel)
{
$this->authorize('store', $idOrModel);
if(request()->get('create_shipment')) {
$shipment = $this->shipmentService->create($idOrModel);
return redirect(route('shipments.show', ['shipment' => $shipment]));
}
return parent::update($idOrModel);
}
/**
* For the index controller action
*
* @return View
*/
public function renderOrderIndex() {
$modelId = ($this->forModelInstance) ? $this->forModelInstance->id : null;
$saveRoute = $this->modelService->getSaveRoute($this->slug, $modelId);
$successes = (Session::has('successes')) ? Session::get('successes') : new MessageBag();
$siteSlug = !$this->siteService->getCurrentSite()->exists ? null : $this->siteService->getCurrentSite()->slug;
$thumbnail = '';
if(is_a($this->forModelInstance, HasThumbnailInterface::class)) {
$thumbnail = $this->forModelInstance->getThumbnail();
};
if(is_a($this->forModelInstance, DisplayNameInterface::class)) {
$displayName = $this->forModelInstance->getDisplayName();
} else {
$displayName = $this->section->getSectionNewModel();
}
return \View::make('KMS::orders/index', [
'sectionTitle' => $this->section->getSectionTitle(),
'sectionTabs' => $this->section->getTabs(),
'slug' => $this->slug,
'siteSlug' => $siteSlug,
'saveRoute' => $saveRoute,
'successes' => $successes,
'models' => $this->modelService->getModelsForSideBar(),
'maxUploadSize' => KommaHelpers::fileUploadMaxSize(),
'maxPostSize' => KommaHelpers::maxPostSize(),
'modelClassName' => $this->classModelName,
'showEntity' => $this->showEntity,
'thumbnail' => $thumbnail,
'displayName' => $displayName,
'currentModel' => $this->forModelInstance,
'submitButtonLabel' => $this->section->getSubmitButtonLabel(),
'preventNavigationTranslation' => json_encode(__('KMS::prevent_navigation'))
]);
}
/**
* Makes a full width view. The sidebar is not needed
*
* @return View
*/
protected function makeView(): View
{
$tabslug = null !== Request::get('tabslug') ? Request::get('tabslug') : Session::get('tabslug', '');
$sessionData = [
'tabslug' => $tabslug
];
$modelId = ($this->forModelInstance) ? $this->forModelInstance->id : null;
$saveRoute = $this->modelService->getSaveRoute($this->slug, $modelId);
$successes = (Session::has('successes')) ? Session::get('successes') : new MessageBag();
$thumbnail = '';
if(is_a($this->forModelInstance, HasThumbnailInterface::class)) {
$thumbnail = $this->forModelInstance->getThumbnail();
};
if(is_a($this->forModelInstance, DisplayNameInterface::class)) {
$displayName = $this->forModelInstance->getDisplayName();
} else {
$displayName = $this->section->getSectionNewModel();
}
// $sideBarModels = $this->modelService->getModelsForSideBar();p
$siteSlug = !$this->siteService->getCurrentSite()->exists ? null : $this->siteService->getCurrentSite()->slug;
return \View::make('KMS::section.fullwidth', [
'sectionTitle' => $this->section->getSectionTitle(),
'sectionTabs' => $this->section->getTabs(),
'slug' => $this->slug,
'siteSlug' => $siteSlug,
'saveRoute' => $saveRoute,
'successes' => $successes,
'models' => $this->modelService->getModelsForSideBar(),
'maxUploadSize' => KommaHelpers::fileUploadMaxSize(),
'maxPostSize' => KommaHelpers::maxPostSize(),
'modelClassName' => $this->classModelName,
'showEntity' => $this->showEntity,
'thumbnail' => $thumbnail,
'displayName' => $displayName,
'currentModel' => $this->forModelInstance,
'submitButtonLabel' => $this->section->getSubmitButtonLabel(),
'preventNavigationTranslation' => json_encode(__('kms/prevent-navigation'))
])->with($sessionData);
}
/**
* Users hitting this controller method will get a form which tells them
* if they need to pay for an order or if it has been paid already.
* If they need to pay for an order they can follow a redirect to the PSP where
* they actually can pay.
*
* Notice, the url is secured by a signature. Only users with the right signature
* can view the link
*
* @param \Illuminate\Http\Request $request
* @param Order $order
* @see OrderApiController::
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function manualPaymentForm(\Illuminate\Http\Request $request, Order $order) {
if (! $request->hasValidSignature() ) abort(401); //Only allow signed routes.
/** @var Transaction $latestTransaction */
$latestTransaction = $order->transactions()->latest()->first();
return view('shop.pages.checkout.manual_payment', [
'order' => $order,
'latestTransaction' => $latestTransaction
]);
}
/**
* @param Order $order
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function viewInvoice(Order $order)
{
return $this->invoiceService->getForOrderAsPDF($order);
}
/**
* @param Order $order
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public function downloadInvoice(Order $order)
{
return $this->invoiceService->getForOrderAsPDFDownload($order);
}
/**
* @param Order $order
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function createCreditInvoice(Order $order)
{
$order->credit_invoice_number = (string) $this->creditInvoiceNumberGenerator->next();
$order->save();
$this->creditInvoiceService->getForOrderAsView($order); //Generates it.
return redirect()->back()->withSuccess(__('KMS::orders.created_credit_invoice'));
}
/**
* @param Order $order
*
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function viewCreditInvoice(Order $order)
{
if($order->credit_invoice_number)
return $this->creditInvoiceService->getForOrderAsPDF($order);
else
return redirect()->back()->withErrors(__('KMS::orders.create_credit_invoice_first'));
}
/**
* @param Order $order
*
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\StreamedResponse
*/
public function downloadCreditInvoice(Order $order)
{
if($order->credit_invoice_number)
return $this->creditInvoiceService->getForOrderAsPDFDownload($order);
else
return redirect()->back()->withErrors(__('KMS::orders.create_credit_invoice_first'));
}
}