/home/brandsfa/.trash/app/Http/Controllers/Admin/Product/ProductController.php
<?php
namespace App\Http\Controllers\Admin\Product;
use App\Contracts\Repositories\AttributeRepositoryInterface;
use App\Contracts\Repositories\BannerRepositoryInterface;
use App\Contracts\Repositories\BrandRepositoryInterface;
use App\Contracts\Repositories\CartRepositoryInterface;
use App\Contracts\Repositories\CategoryRepositoryInterface;
use App\Contracts\Repositories\ColorRepositoryInterface;
use App\Contracts\Repositories\DealOfTheDayRepositoryInterface;
use App\Contracts\Repositories\FlashDealProductRepositoryInterface;
use App\Contracts\Repositories\ProductRepositoryInterface;
use App\Contracts\Repositories\ReviewRepositoryInterface;
use App\Contracts\Repositories\TranslationRepositoryInterface;
use App\Contracts\Repositories\VendorRepositoryInterface;
use App\Contracts\Repositories\WishlistRepositoryInterface;
use App\Enums\ViewPaths\Admin\Product;
use App\Enums\WebConfigKey;
use App\Events\ProductRequestStatusUpdateEvent;
use App\Exports\ProductListExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Admin\ProductDenyRequest;
use App\Http\Requests\ProductAddRequest;
use App\Http\Requests\ProductUpdateRequest;
use App\Services\ProductService;
use App\Traits\FileManagerTrait;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use mysql_xdevapi\Exception;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class ProductController extends BaseController
{
use FileManagerTrait {
delete as deleteFile;
update as updateFile;
}
public function __construct(
private readonly CategoryRepositoryInterface $categoryRepo,
private readonly BrandRepositoryInterface $brandRepo,
private readonly ProductRepositoryInterface $productRepo,
private readonly VendorRepositoryInterface $sellerRepo,
private readonly ColorRepositoryInterface $colorRepo,
private readonly AttributeRepositoryInterface $attributeRepo,
private readonly TranslationRepositoryInterface $translationRepo,
private readonly CartRepositoryInterface $cartRepo,
private readonly WishlistRepositoryInterface $wishlistRepo,
private readonly FlashDealProductRepositoryInterface $flashDealProductRepo,
private readonly DealOfTheDayRepositoryInterface $dealOfTheDayRepo,
private readonly ReviewRepositoryInterface $reviewRepo,
private readonly BannerRepositoryInterface $bannerRepo,
)
{
}
/**
* @param Request|null $request
* @param string|null $type
* @return View Index function is the starting point of a controller
* Index function is the starting point of a controller
*/
public function index(Request|null $request, string $type = null): View
{
return $this->getListView(request: $request, type: $type);
}
public function getAddView(): View
{
$categories = $this->categoryRepo->getListWhere(filters: ['position' => 0], dataLimit: 'all');
$brands = $this->brandRepo->getListWhere(dataLimit: 'all');
$brandSetting = getWebConfig(name: 'product_brand');
$digitalProductSetting = getWebConfig(name: 'digital_product');
$colors = $this->colorRepo->getList(orderBy: ['name' => 'desc'], dataLimit: 'all');
$attributes = $this->attributeRepo->getList(orderBy: ['name' => 'desc'], dataLimit: 'all');
$languages = getWebConfig(name: 'pnc_language') ?? null;
$defaultLanguage = $languages[0];
return view(Product::ADD[VIEW], compact('categories', 'brands', 'brandSetting', 'digitalProductSetting', 'colors', 'attributes', 'languages', 'defaultLanguage'));
}
public function add(ProductAddRequest $request, ProductService $service): JsonResponse|RedirectResponse
{
if ($request->ajax()) {
return response()->json([], 200);
}
$dataArray = $service->getAddProductData(request: $request, addedBy: 'admin');
$savedProduct = $this->productRepo->add(data: $dataArray);
$this->productRepo->addRelatedTags(request: $request, product: $savedProduct);
$this->translationRepo->add(request: $request, model: 'App\Models\Product', id: $savedProduct->id);
Toastr::success(translate('product_added_successfully'));
return redirect()->route('admin.products.list', ['in_house']);
}
public function getListView(Request $request, string $type): View
{
$filters = [
'added_by' => $type,
'request_status' => $request['status'],
'seller_id' => $request['seller_id'],
'brand_id' => $request['brand_id'],
'category_id' => $request['category_id'],
'sub_category_id' => $request['sub_category_id'],
'sub_sub_category_id' => $request['sub_sub_category_id'],
];
$products = $this->productRepo->getListWhere(orderBy: ['id' => 'desc'], searchValue: $request['searchValue'], filters: $filters, relations: ['translations'], dataLimit: getWebConfig(name: WebConfigKey::PAGINATION_LIMIT));
$sellers = $this->sellerRepo->getByStatusExcept(status: 'pending', relations: ['shop'], paginateBy: getWebConfig(name: WebConfigKey::PAGINATION_LIMIT));
$brands = $this->brandRepo->getListWhere(filters: ['status' => 1], dataLimit: 'all');
$categories = $this->categoryRepo->getListWhere(filters: ['position' => 0], dataLimit: 'all');
$subCategory = $this->categoryRepo->getFirstWhere(params: ['id' => $request['sub_category_id']]);
$subSubCategory = $this->categoryRepo->getFirstWhere(params: ['id' => $request['sub_sub_category_id']]);
return view(Product::LIST[VIEW], compact('products', 'sellers', 'brands',
'categories', 'subCategory', 'subSubCategory', 'filters', 'type'));
}
public function getUpdateView(string|int $id): View
{
$product = $this->productRepo->getFirstWhereWithoutGlobalScope(params: ['id' => $id], relations: ['translations']);
$product['colors'] = json_decode($product['colors']);
$categories = $this->categoryRepo->getListWhere(filters: ['position' => 0], dataLimit: 'all');
$brands = $this->brandRepo->getListWhere(dataLimit: 'all');
$brandSetting = getWebConfig(name: 'product_brand');
$digitalProductSetting = getWebConfig(name: 'digital_product');
$languages = getWebConfig(name: 'pnc_language') ?? null;
$colors = $this->colorRepo->getList(orderBy: ['name' => 'desc'], dataLimit: 'all');
$attributes = $this->attributeRepo->getList(orderBy: ['name' => 'desc'], dataLimit: 'all');
$defaultLanguage = $languages[0];
return view(Product::UPDATE[VIEW], compact('product', 'categories', 'brands', 'brandSetting', 'digitalProductSetting', 'colors', 'attributes', 'languages', 'defaultLanguage'));
}
public function update(ProductUpdateRequest $request, ProductService $service, string|int $id): JsonResponse|RedirectResponse
{
if ($request->ajax()) {
return response()->json([], 200);
}
$product = $this->productRepo->getFirstWhereWithoutGlobalScope(params: ['id' => $id], relations: ['translations']);
$dataArray = $service->getUpdateProductData(request: $request, product: $product, updateBy: 'admin');
$this->productRepo->update(id: $id, data: $dataArray);
$this->productRepo->addRelatedTags(request: $request, product: $product);
$this->translationRepo->update(request: $request, model: 'App\Models\Product', id: $id);
Toastr::success(translate('product_updated_successfully'));
return redirect()->route(Product::VIEW[ROUTE],['addedBy'=>$product['added_by'],'id'=>$product['id']]);
}
public function getView(string $addedBy,string|int $id): View
{
$productActive = $this->productRepo->getFirstWhereActive(params: ['id' => $id]);
$relations = ['category', 'brand', 'reviews', 'rating', 'orderDetails', 'orderDelivered','translations'];
$product = $this->productRepo->getFirstWhereWithoutGlobalScope(params: ['id' => $id], relations: $relations);
$product->orderDelivered->map(function ($order) use ($product) {
$product->priceSum = $order->sum('price');
$product->qtySum = $order->sum('qty');
$product->discountSum = $order->sum('discount');
});
$productColors = [];
$colors = json_decode($product['colors']);
foreach ($colors as $color) {
$getColor = $this->colorRepo->getFirstWhere(params: ['code' => $color]);
if ($getColor) {
$productColors[$getColor['name']] = $colors;
}
}
$reviews = $this->reviewRepo->getListWhere(filters: ['product_id' => ['product_id' => $id], 'whereNull' => ['column' => 'delivery_man_id']], dataLimit: getWebConfig(name: 'pagination_limit'));
return view(Product::VIEW[VIEW], compact('product', 'reviews', 'productActive', 'productColors','addedBy'));
}
public function getSkuCombinationView(Request $request, ProductService $service): JsonResponse
{
$combinationView = $service->getSkuCombinationView(request: $request);
return response()->json(['view' => $combinationView]);
}
public function updateFeaturedStatus(Request $request): JsonResponse
{
$status = $request['status'];
$productId = $request['id'];
$product = $this->productRepo->getFirstWhere(params: ['id' => $productId]);
$updateData = [
'featured' => $product['featured'] ? 0 : 1
];
$this->productRepo->update(id: $productId, data: $updateData);
return response()->json($status);
}
public function updateStatus(Request $request): JsonResponse
{
$status = $request->get('status', 0);
$productId = $request['id'];
$product = $this->productRepo->getFirstWhere(params: ['id' => $productId]);
$success = 1;
if ($status == 1) {
$success = $product->added_by == 'seller' && ($product['request_status'] == 0 || $product['request_status'] == 2) ? 0 : 1;
}
$updateData = ['status' => $status];
$data = $success ? $this->productRepo->update(id: $productId, data: $updateData) : null;
return response()->json([
'success' => $success,
'data' => $data,
'message' => $success ? translate("status_updated_successfully") : translate("status_updated_failed").' '.translate("Product_must_be_approved"),
], 200);
}
public function deleteImage(Request $request, ProductService $service): RedirectResponse
{
$this->deleteFile(filePath: '/product/' . $request['image']);
$product = $this->productRepo->getFirstWhere(params: ['id' => $request['id']]);
if (count(json_decode($product['images'])) < 2) {
Toastr::warning(translate('you_can_not_delete_all_images'));
return back();
}
$imageProcessing = $service->deleteImage(request: $request, product: $product);
$updateData = [
'images' => json_encode($imageProcessing['images']),
'color_image' => json_encode($imageProcessing['color_images']),
];
$this->productRepo->update(id: $request['id'], data: $updateData);
Toastr::success(translate('product_image_removed_successfully'));
return back();
}
public function getCategories(Request $request, ProductService $service): JsonResponse
{
$parentId = $request['parent_id'];
$filter = ['parent_id' => $parentId];
$categories = $this->categoryRepo->getListWhere(filters: $filter, dataLimit: 'all');
$dropdown = $service->getCategoryDropdown(request: $request, categories: $categories);
$childCategories = '';
if (count($categories) == 1) {
$subCategories = $this->categoryRepo->getListWhere(filters: ['parent_id' => $categories[0]['id']], dataLimit: 'all');
$childCategories = $service->getCategoryDropdown(request: $request, categories: $subCategories);
}
return response()->json([
'select_tag' => $dropdown,
'sub_categories' => count($categories) == 1 ? $childCategories : '',
]);
}
public function exportList(Request $request, string $type): BinaryFileResponse
{
$filters = [
'added_by' => $type,
'request_status' => $request['status'],
'seller_id' => $request['seller_id'],
'brand_id' => $request['brand_id'],
'category_id' => $request['category_id'],
'sub_category_id' => $request['sub_category_id'],
'sub_sub_category_id' => $request['sub_sub_category_id'],
];
$products = $this->productRepo->getListWhere(orderBy: ['id' => 'desc'], searchValue: $request['searchValue'], filters: $filters, relations: ['translations'], dataLimit: 'all');
//export from product
$category = (!empty($request['category_id']) && $request->has('category_id')) ? $this->categoryRepo->getFirstWhere(params: ['id' => $request['category_id']]) : 'all';
$subCategory = (!empty($request->sub_category_id) && $request->has('sub_category_id')) ? $this->categoryRepo->getFirstWhere(params: ['id' => $request['sub_category_id']]) : 'all';
$subSubCategory = (!empty($request->sub_sub_category_id) && $request->has('sub_sub_category_id')) ? $this->categoryRepo->getFirstWhere(params: ['id' => $request['sub_sub_category_id']]) : 'all';
$brand = (!empty($request->brand_id) && $request->has('brand_id')) ? $this->brandRepo->getFirstWhere(params: ['id' => $request->brand_id]) : 'all';
$seller = (!empty($request->seller_id) && $request->has('seller_id')) ? $this->sellerRepo->getFirstWhere(params: ['id' => $request->seller_id]) : '';
$data = [
'products' => $products,
'category' => $category,
'sub_category' => $subCategory,
'sub_sub_category' => $subSubCategory,
'brand' => $brand,
'searchValue' => $request['searchValue'],
'type' => $request->type ?? '',
'seller' => $seller,
'status' => $request->status ?? '',
];
return Excel::download(new ProductListExport($data), ucwords($request['type']) . '-' . 'product-list.xlsx');
}
public function getBarcodeView(Request $request, string|int $id): View|RedirectResponse
{
if ($request['limit'] > 270) {
Toastr::warning(translate('you_can_not_generate_more_than_270_barcode'));
return back();
}
$product = $this->productRepo->getFirstWhere(params: ['id' => $id]);
$rangeData = range(1, $request->limit ?? 4);
$barcodes = array_chunk($rangeData, 24);
return view(Product::BARCODE_VIEW[VIEW], compact('product', 'barcodes'));
}
public function getStockLimitListView(Request $request, string $type): View
{
$stockLimit = getWebConfig(name: 'stock_limit');
$sortOrderQty = $request['sortOrderQty'];
$searchValue = $request['searchValue'];
$withCount = ['orderDetails'];
$status = $request['status'];
$filters = [
'added_by' => $type,
'product_type' => 'physical',
'request_status' => $request['status'],
];
$orderBy = [];
if ($sortOrderQty == 'quantity_asc') {
$orderBy = ['current_stock' => 'asc'];
}else if ($sortOrderQty == 'quantity_desc') {
$orderBy = ['current_stock' => 'desc'];
} elseif ($sortOrderQty == 'order_asc') {
$orderBy = ['order_details_count' => 'asc'];
} elseif ($sortOrderQty == 'order_desc') {
$orderBy = ['order_details_count' => 'desc'];
} elseif ($sortOrderQty == 'default') {
$orderBy = ['id' => 'asc'];
}
$products = $this->productRepo->getStockLimitListWhere(orderBy: $orderBy, searchValue: $searchValue, filters: $filters, withCount: $withCount, relations: ['translations'], dataLimit: getWebConfig(name: WebConfigKey::PAGINATION_LIMIT));
return view(Product::STOCK_LIMIT[VIEW], compact('products', 'searchValue', 'status', 'sortOrderQty', 'stockLimit'));
}
public function delete(string|int $id, ProductService $service): RedirectResponse
{
$product = $this->productRepo->getFirstWhere(params: ['id' => $id]);
if ($product) {
$this->translationRepo->delete(model: 'App\Models\Product', id: $id);
$this->cartRepo->delete(params: ['product_id' => $id]);
$this->wishlistRepo->delete(params: ['product_id' => $id]);
$this->flashDealProductRepo->delete(params: ['product_id' => $id]);
$this->dealOfTheDayRepo->delete(params: ['product_id' => $id]);
$service->deleteImages(product: $product);
$this->productRepo->delete(params: ['id' => $id]);
$bannerIds = $this->bannerRepo->getListWhere(filters:['resource_type'=>'product','resource_id'=>$product['id']])->pluck('id');
$bannerIds->map(function ($bannerId){
$this->bannerRepo->update(id:$bannerId,data: ['published'=>0,'resource_id'=>null]);
});
Toastr::success(translate('product_removed_successfully'));
}else {
Toastr::error(translate('invalid_product'));
}
return back();
}
public function getVariations(Request $request): JsonResponse
{
$product = $this->productRepo->getFirstWhere(params: ['id' => $request['id']]);
return response()->json([
'view' => view(Product::GET_VARIATIONS[VIEW], compact('product'))->render()
]);
}
public function updateQuantity(Request $request): RedirectResponse
{
$variations = [];
$stockCount = $request['current_stock'];
if ($request->has('type')) {
foreach ($request['type'] as $key => $str) {
$item = [];
$item['type'] = $str;
$item['price'] = currencyConverter(amount: abs($request['price_' . str_replace('.', '_', $str)]));
$item['sku'] = $request['sku_' . str_replace('.', '_', $str)];
$item['qty'] = abs($request['qty_' . str_replace('.', '_', $str)]);
$variations[] = $item;
}
}
$dataArray = [
'current_stock' => $stockCount,
'variation' => json_encode($variations),
];
if ($stockCount >= 0) {
$this->productRepo->update(id: $request['product_id'], data: $dataArray);
Toastr::success(translate('product_quantity_updated_successfully'));
return back();
}
Toastr::warning(translate('product_quantity_can_not_be_less_than_0_'));
return back();
}
public function getBulkImportView(): View
{
return view(Product::BULK_IMPORT[VIEW]);
}
public function importBulkProduct(Request $request, ProductService $service): RedirectResponse
{
$dataArray = $service->getImportBulkProductData(request: $request, addedBy: 'admin');
if (!$dataArray['status']) {
Toastr::error($dataArray['message']);
return back();
}
$this->productRepo->addArray(data: $dataArray['products']);
Toastr::success($dataArray['message']);
return back();
}
public function updatedProductList(Request $request): View
{
$filters = [
'added_by' => 'seller',
'is_shipping_cost_updated' => 0,
];
$searchValue = $request['searchValue'];
$products = $this->productRepo->getListWhere(orderBy: ['id' => 'desc'], searchValue: $searchValue, filters: $filters, relations: ['translations'], dataLimit: getWebConfig(name: WebConfigKey::PAGINATION_LIMIT));
return view(Product::UPDATED_PRODUCT_LIST[VIEW], compact('products', 'searchValue'));
}
public function updatedShipping(Request $request): JsonResponse
{
$product = $this->productRepo->getFirstWhereWithoutGlobalScope(params: ['id' => $request['id']], relations: ['translations']);
$dataArray = ['is_shipping_cost_updated' => $request['status']];
if ($request['status'] == 1) {
$dataArray += ['shipping_cost' => $product['temp_shipping_cost']];
}
$this->productRepo->update(id: $request['id'], data: $dataArray);
return response()->json(['message' => translate('status_updated_successfully')], 200);
}
public function deny(ProductDenyRequest $request): JsonResponse
{
$dataArray = [
'request_status' => 2,
'status' => 0,
'denied_note' => $request['denied_note'],
];
$this->productRepo->update(id: $request['id'], data: $dataArray);
$product = $this->productRepo->getFirstWhereWithoutGlobalScope(params: ['id' => $request['id']], relations: ['translations']);
$vendor = $this->sellerRepo->getFirstWhere(params: ['id'=>$product['user_id']]);
if ($vendor['cm_firebase_token']){
ProductRequestStatusUpdateEvent::dispatch('product_request_rejected_message', 'seller', $vendor['app_language'] ?? getDefaultLanguage(),$vendor['cm_firebase_token']);
}
return response()->json(['message'=>translate('product_request_denied').'.']);
}
public function approveStatus(Request $request): JsonResponse
{
$product = $this->productRepo->getFirstWhereWithoutGlobalScope(params: ['id' => $request['id']], relations: ['translations']);
$dataArray = [
'request_status' => ($product['request_status'] == 0) ? 1 : 0
];
$this->productRepo->update(id: $request['id'], data: $dataArray);
$vendor = $this->sellerRepo->getFirstWhere(params: ['id'=>$product['user_id']]);
if ($vendor['cm_firebase_token']) {
ProductRequestStatusUpdateEvent::dispatch('product_request_approved_message', 'seller', $vendor['app_language'] ?? getDefaultLanguage(), $vendor['cm_firebase_token']);
}
return response()->json(['message'=>translate('product_request_approved').'.']);
}
public function getSearchedProductsView(Request $request):JsonResponse
{
$searchValue = $request['searchValue'] ?? null;
$products = $this->productRepo->getListWhere(
searchValue: $searchValue,
filters: [
'added_by' => 'in_house',
'status' => 1,
'category_id' => $request['category_id'],
'code' => $request['name'],
],
dataLimit:getWebConfig(name:'pagination_limit')
);
return response()->json([
'count' => $products->count(),
'result' => view(Product::SEARCH[VIEW], compact('products'))->render(),
]);
}
}