/home/brandsfa/www/app/Http/Controllers/Admin/POS/CartController.php
<?php
namespace App\Http\Controllers\Admin\POS;
use App\Contracts\Repositories\ColorRepositoryInterface;
use App\Contracts\Repositories\CustomerRepositoryInterface;
use App\Contracts\Repositories\ProductRepositoryInterface;
use App\Enums\SessionKey;
use App\Enums\ViewPaths\Admin\Cart;
use App\Enums\ViewPaths\Admin\POS;
use App\Http\Controllers\BaseController;
use App\Services\CartService;
use App\Services\POSService;
use App\Traits\CalculatorTrait;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Str;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class CartController extends BaseController
{
use CalculatorTrait;
/**
* @param ProductRepositoryInterface $productRepo
* @param ColorRepositoryInterface $colorRepo
* @param CustomerRepositoryInterface $customerRepo
* @param CartService $cartService
* @param POSService $POSService
*/
public function __construct(
private readonly ProductRepositoryInterface $productRepo,
private readonly ColorRepositoryInterface $colorRepo,
private readonly CustomerRepositoryInterface $customerRepo,
private readonly CartService $cartService,
private readonly POSService $POSService,
)
{
}
public function index(?Request $request, string $type = null): View|Collection|LengthAwarePaginator|null|callable|RedirectResponse
{
// TODO: Implement index() method.
}
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function getVariantPrice(Request $request):JsonResponse
{
$product = $this->productRepo->getFirstWhere(params:['id'=>$request['id']]);
$colorName = $this->colorRepo->getFirstWhere(['code'=>$request['color']])->name ?? null;
$data = $this->cartService->getVariantData(
request:$request,product: $product,colorName:$colorName
);
return response()->json($data);
}
/**
* @param Request $request
* @return JsonResponse
*/
public function updateQuantity(Request $request):JsonResponse
{
$cartId = session(SessionKey::CURRENT_USER);
if($request['quantity'] > 0){
$product = $this->productRepo->getFirstWhere(params:['id'=>$request['key']]);
$quantity = $this->cartService->getQuantityAndUpdateTime(request: $request,product:$product);
$cartItems = $this->getCartData(cartName: $cartId);
if($product['product_type'] =='physical' && $quantity < 0)
{
return response()->json([
'qty' => $quantity,
'productType' => $product['product_type'],
'view' => view(Cart::CART[VIEW],compact('cartId','cartItems'))->render()
]);
}else{
return response()->json([
'quantityUpdate'=>1,
'view' => view(Cart::CART[VIEW],compact('cartId','cartItems'))->render()
]);
}
}else{
$cartItems = $this->getCartData(cartName: $cartId);
return response()->json([
'upQty'=>'zeroNegative',
'view' => view(Cart::CART[VIEW],compact('cartId','cartItems'))->render()
]);
}
}
public function addToCart(Request $request):JsonResponse
{
$cartId =session(SessionKey::CURRENT_USER);
$product = $this->productRepo->getFirstWhere(params:['id'=>$request['id']]);
$colorName = $this->colorRepo->getFirstWhere(['code'=>$request['color']])->name ?? null;
$variations['color'] = $colorName;
$variant = $this->cartService->makeVariation(
request:$request,
colorName: $colorName,
choiceOptions: json_decode($product['choice_options'])
);
foreach (json_decode($product['choice_options']) as $choice) {
$variations[$choice->title] = $request[$choice->name];
}
$discount = $this->getDiscountAmount(price: $product['unit_price'], discount: $product['discount'],discountType: $product['discount_type']);
$price = $product['unit_price'] ;
$cartData = session($cartId);
if (session()->has($cartId) && count($cartData) > 0) {
foreach ($cartData as $key => $cartItem) {
if (is_array($cartItem) && $cartItem['id'] == $request['id'] && $cartItem['variant'] == $variant) {
if ($variant != null) {
$price = $this->cartService->getVariationPrice(variation: json_decode($product['variation']),variant: $variant);
}
$currentQty = $this->cartService->checkCurrentStock(variant: $variant,variation: json_decode($product['variation']),productQty: $product['current_stock'],quantity: $request['quantity_in_cart']);
if($product['product_type'] == 'physical' && $currentQty<0)
{
$cartItems = $this->getCartData(cartName: $cartId);
return response()->json([
'data' => 0,
'view' => view(Cart::CART[VIEW],compact('cartId','cartItems'))->render()
]);
}
$cartItem = $this->cartService->addCartDataOnSession(
product: $product,
quantity: $request['quantity_in_cart'],
price: $price,
discount: $discount,
variant: $variant,
variations: $variations
);
unset($cartData[$key]);
$cartData[] = $cartItem;
session([$cartId => $cartData]);
$getCurrentCustomerData = $this->getCustomerDataFromSessionForPOS();
$summaryData = array_merge($this->POSService->getSummaryData(), $getCurrentCustomerData);
$cartItems = $this->getCartData(cartName: $cartId);
return response()->json([
'data' => 1,
'inCartData' => 1,
'requestQuantity' => $request['quantity_in_cart'],
'view' => view(Cart::SUMMARY[VIEW],compact('summaryData','cartItems'))->render(),
]);
}
}
}
if ($variant != null) {
$price = $this->cartService->getVariationPrice(variation: json_decode($product['variation']),variant: $variant);
}
$currentQty = $this->cartService->checkCurrentStock(variant: $variant,variation: json_decode($product['variation']),productQty: $product['current_stock'],quantity: $request['quantity']);
if($product['product_type'] == 'physical' && $currentQty<0)
{
$cartItems = $this->getCartData(cartName: $cartId);
return response()->json([
'data' => 0,
'view' => view(Cart::CART[VIEW],compact('cartId','cartItems'))->render()
]);
}
$sessionData = $this->cartService->addCartDataOnSession(
product: $product,
quantity: $request['quantity'],
price: $price,
discount: $discount,
variant: $variant,
variations: $variations
);
$cartItems = $this->getCartData(cartName: $cartId);
return response()->json([
'data' => $sessionData,
'view' => view(Cart::CART[VIEW],compact('cartId','cartItems'))->render()
]);
}
/**
* @param Request $request
* @return JsonResponse
*/
public function removeCart(Request $request) :JsonResponse
{
$cartId = session(SessionKey::CURRENT_USER);
$cart = session($cartId);
$cartKeeper = [];
if (session()->has($cartId) && count($cart) > 0) {
foreach ($cart as $cartItem) {
if (is_array($cartItem) ){
if ($cartItem['id'] != $request['id']) {
$cartKeeper[] = $cartItem;
}else{
if($cartItem['variant'] != $request['variant']){
$cartKeeper[] = $cartItem;
}
}
}
}
}
session()->put($cartId, $cartKeeper);
$cartItems = $this->getCartData(cartName: $cartId);
return response()->json(
['view' => view(Cart::CART[VIEW],compact('cartId','cartItems'))->render()]
);
}
/**
* @return RedirectResponse
*/
public function clearSessionCartIds():RedirectResponse
{
session()->forget(SessionKey::CART_NAME);
session()->forget(session(SessionKey::CURRENT_USER));
session()->forget(SessionKey::CURRENT_USER);
return redirect()->route(POS::INDEX[ROUTE]);
}
/**
* @return JsonResponse
*/
public function getCartIds(): JsonResponse
{
$this->cartService->getCartKeeper();
$getCurrentCustomerData = $this->getCustomerDataFromSessionForPOS();
$summaryData = array_merge($this->POSService->getSummaryData(), $getCurrentCustomerData);
$cartItems = $this->getCartData(cartName: session(SessionKey::CURRENT_USER));
return response()->json([
'view' => view(Cart::SUMMARY[VIEW], compact('summaryData','cartItems'))->render(),
]);
}
/**
* @return JsonResponse
*/
public function emptyCart():JsonResponse
{
$cartId =session(SessionKey::CURRENT_USER);
session()->forget($cartId);
$this->cartService->getNewCartSession(cartId:$cartId);
$getCurrentCustomerData = $this->getCustomerDataFromSessionForPOS();
$summaryData = array_merge($this->POSService->getSummaryData(), $getCurrentCustomerData);
$cartItems = $this->getCartData(cartName: $cartId);
return response()->json([
'view' => view(Cart::SUMMARY[VIEW],compact('summaryData','cartItems'))->render(),
]);
}
/**
* @param Request $request
* @return RedirectResponse
*/
public function changeCart(Request $request):RedirectResponse
{
$this->cartService->customerOnHoldStatus(status: true);
session()->put(SessionKey::CURRENT_USER, $request['cart_id']);
$this->cartService->customerOnHoldStatus(status: false);
Toastr::success($request['cart_id'].' '.translate('order_is_now_resumed'));
return redirect()->route(POS::INDEX[ROUTE]);
}
/**
* @return RedirectResponse
*/
public function addNewCartId():RedirectResponse
{
$cart = session(session(SessionKey::CURRENT_USER));
if (session()->has(session(SessionKey::CURRENT_USER)) && count($cart) > 0) {
Toastr::success(translate('this_order_is_now_on_hold'));
}
$this->cartService->customerOnHoldStatus(status: true);
$this->cartService->getNewCartId();
return redirect()->route(POS::INDEX[ROUTE]);
}
/**
* @return array
*/
protected function getCustomerDataFromSessionForPOS():array
{
if( Str::contains(session(SessionKey::CURRENT_USER), 'walking-customer'))
{
$currentCustomer = 'Walking Customer';
$currentCustomerData =$this->customerRepo->getFirstWhere(params:['id'=>'0']);
}else{
$userId = explode('-',session(SessionKey::CURRENT_USER))[2];
$currentCustomerData = $this->customerRepo->getFirstWhere(params:['id'=>$userId]);
$currentCustomer = $currentCustomerData['f_name'].' '.$currentCustomerData['l_name']. ' (' .$currentCustomerData['phone'].')';
}
return [
'currentCustomer' => $currentCustomer,
'currentCustomerData' => $currentCustomerData
];
}
/**
* @param string $cartName
* @return array
* @function getCustomerCartData ,used for process data
*/
protected function getCustomerCartData(string $cartName):array
{
$customerCartData = [];
if (Str::contains($cartName, 'walking-customer')) {
$customerName = 'Walking Customer';
$customerPhone = "";
$customerId = 0 ;
} else {
$customerId = explode('-', $cartName)[2];
$currentCustomerData = $this->customerRepo->getFirstWhere(params: ['id' => $customerId]);
$customerName = $currentCustomerData['f_name'] . ' ' . $currentCustomerData['l_name'];
$customerPhone = $currentCustomerData['phone'];
}
$customerCartData[$cartName] = [
'customerName' => $customerName,
'customerPhone' => $customerPhone,
'customerId'=>$customerId,
];
return $customerCartData;
}
protected function calculateCartItemsData(string $cartName, array $customerCartData):array
{
$cartItemValue = [];
$subTotalCalculation = [
'countItem' => 0,
'taxCalculate' => 0 ,
'totalTaxShow' => 0,
'totalTax' => 0,
'subtotal' => 0,
'discountOnProduct' => 0,
'productSubtotal' => 0,
];
if(session()->get($cartName)) {
foreach (session()->get($cartName) as $cartItem) {
if (is_array($cartItem)) {
$product = $this->productRepo->getFirstWhere(params: ['id' => $cartItem['id']]);
$subTotalCalculation = $this->cartService->getCartSubtotalCalculation(
product: $product,
cartItem: $cartItem,
calculation : $subTotalCalculation
);
if ($cartItem['customerId'] == $customerCartData[$cartName]['customerId']) {
$cartItem['productSubtotal'] = $subTotalCalculation['productSubtotal'];
$subTotalCalculation['customerOnHold']=$cartItem['customerOnHold'];
$cartItemValue[] = $cartItem;
}
}
}
}
$totalCalculation = $this->cartService->getTotalCalculation(
subTotalCalculation:$subTotalCalculation,cartName: $cartName
);
return [
'countItem' => $subTotalCalculation['countItem'],
'total' => $totalCalculation['total'],
'subtotal' => $subTotalCalculation['subtotal'],
'taxCalculate' => $subTotalCalculation['taxCalculate'],
'totalTaxShow' => $subTotalCalculation['totalTaxShow'],
'totalTax' => $subTotalCalculation['totalTax'],
'discountOnProduct' => $subTotalCalculation['discountOnProduct'],
'productSubtotal' => $subTotalCalculation['productSubtotal'],
'cartItemValue' => $cartItemValue,
'couponDiscount' => $totalCalculation['couponDiscount'],
'extraDiscount' => $totalCalculation['extraDiscount'],
'customerOnHold' => $subTotalCalculation['customerOnHold']??false,
];
}
protected function getCartData(string $cartName):array
{
$customerCartData =$this->getCustomerCartData(cartName:$cartName);
$cartItemData = $this->calculateCartItemsData(cartName: $cartName,customerCartData:$customerCartData);
return array_merge($customerCartData[$cartName],$cartItemData);
}
}