File "ProductApiController.php"
Full Path: /home/clickysoft/public_html/jmapi5.clickysoft.net/app/Http/Controllers/Api/V1/Admin/ProductApiController.php
File size: 17.3 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace App\Http\Controllers\Api\V1\Admin;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Traits\MediaUploadingTrait;
use App\Http\Requests\Admin\StoreProductRequest;
use App\Http\Requests\Admin\UpdateProductRequest;
use App\Http\Resources\Admin\ProductDetailsResource;
use App\Http\Resources\Admin\ProductResource;
use App\Http\Resources\Admin\ProductResourceWithAttributes;
use App\Http\Resources\Admin\ProductSimple;
use App\Models\OrderItems;
use App\Models\Product;
use App\Models\ProductPrice;
use App\Models\ProductVariation;
use App\Models\ProductVariationCombination;
use App\Models\ProductVariationRange;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\Response;
class ProductApiController extends Controller
{
use MediaUploadingTrait;
public function index(Request $request)
{
abort_if(Gate::denies('product_access'), Response::HTTP_FORBIDDEN, '403 Forbidden');
ProductResource::withoutWrapping();
$products = Product::when($request->filled('category'), function ($query) use ($request){
$query->whereHas('category', function ($query) use ($request) {
$query->where('name', 'like', "%{$request->get('category')}%");
$query->orWhere('id', $request->get('category'));
});
})
->when($request->filled('name'), function ($query) use ($request){
$query->where('name', 'like', "%{$request->get('name')}%");
})
->when($request->filled('sku'), function ($query) use ($request){
$query->where('sku', 'like', "%{$request->get('sku')}%");
})
->when($request->filled('is_draft'), function ($query) use ($request){
$query->where('is_draft', $request->get('is_draft'));
})
->when($request->filled('product_type'), function ($query) use ($request){
$query->where('product_type', 'like', "%{$request->get('product_type')}%");
})
->with([
'category',
'variations',
'variations.variation',
'prices',
'prices.combinations',
'prices.priceRanges',
])->orderBy('created_at', 'DESC')->paginate(10);
return ProductResource::collection($products);
}
public function getProductsForOrder(Request $request)
{
$products = Product::when($request->filled('name'), function ($query) use ($request){
$query->where('name', 'like', "%{$request->get('name')}%");
})
->when($request->filled('sku'), function ($query) use ($request){
$query->where('sku', 'like', "%{$request->get('sku')}%");
});
$products = $products->orderBy('name')->get();
ProductSimple::withoutWrapping();
return ProductSimple::collection($products);
}
public function getProductDetails(Product $product)
{
return new ProductDetailsResource($product);
}
public function change_status(Product $product)
{
abort_if(Gate::denies('product_edit'), Response::HTTP_FORBIDDEN, '403 Forbidden');
$product->status = !$product->status;
$product->save();
return response()
->json(['message' => 'Product status updated successfully'], Response::HTTP_OK);
}
public function store(StoreProductRequest $request)
{
DB::beginTransaction();
try {
$product = Product::create([
'vendor_id' => $request['vendor_id'] ?? null,
'sku' => $request['sku'],
'name' => $request['name'],
'description' => $request['description'],
'engraving' => $request['engraving'],
'color_engraving' => $request['color_engraving'],
'engraving_fee' => $request['engraving_fee'],
'status' => $request['status'],
'is_draft' => $request['is_draft'],
'product_type' => $request['product_type'],
'category_id' => $request['category_id'],
'has_variations' => 1,
]);
if ($request->hasFile('featured_image')) {
$product->addMediaFromRequest('featured_image')
->toMediaCollection('product_featured_image', 'product')->save();
}
foreach ($request->file('gallery_images', []) as $file) {
$product->addMedia($file)->toMediaCollection('gallery_image', 'product');
}
$product->handleVariations($request);
DB::commit();
return (new ProductResource($product))
->response()
->setStatusCode(Response::HTTP_CREATED);
} catch (\Exception $e){
\Log::channel('db_errors')->info('Product Create Error');
\Log::channel('db_errors')->info($e->getMessage());
return response()
->json([
'message' => "Can not create product.",
'errors' => ["error" => ["Unable to create product."]]
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function show(Product $product)
{
abort_if(Gate::denies('product_show'), Response::HTTP_FORBIDDEN, '403 Forbidden');
$product = $product->load([
'category',
'variations',
'variations.variation',
'prices',
'prices.combinations',
'prices.priceRanges',
]);
return new ProductResourceWithAttributes($product);
}
public function update(UpdateProductRequest $request, Product $product)
{
DB::beginTransaction();
try {
$product->update([
'category_id' => $request['category_id'],
'vendor_id' => $request['vendor_id'] ?? null,
'sku' => $request['sku'],
'name' => $request['name'],
// 'slug' => $request['slug'],
'description' => $request['description'],
'engraving' => $request['engraving'],
'color_engraving' => $request['color_engraving'],
'engraving_fee' => $request['engraving_fee'],
'has_variations' => 1,
'status' => $request['status'],
'is_draft' => $request['is_draft'],
'product_type' => $request['product_type'],
]);
if ($request->hasFile('featured_image')) {
if (!empty($product->featured_image)) {
$product->clearMediaCollection('product_featured_image');
}
$product->addMediaFromRequest('featured_image')
->toMediaCollection('product_featured_image', 'product');
$product->save();
}
if ($request->hasFile('gallery_images')){
foreach ($request->file('gallery_images', []) as $file) {
$product->addMedia($file)->toMediaCollection('gallery_image', 'product');
}
}
$product->handleVariations($request);
$product->save();
DB::commit();
return (new ProductResource($product))
->response()
->setStatusCode(Response::HTTP_CREATED);
}catch (\Exception $e){
\Log::channel('db_errors')->info('Product Update Error');
\Log::channel('db_errors')->info($e->getMessage());
DB::rollBack();
return response()
->json([
'message' => "Can not update product.",
'errors' => ["error" => ["Unable to update product."]]
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function destroy(Product $product)
{
abort_if(Gate::denies('product_delete'), Response::HTTP_FORBIDDEN, '403 Forbidden');
try {
$product->prices()->delete();
$product->variations()->delete();
ProductVariationCombination::where('product_id', $product->id)->delete();
ProductVariationRange::where('product_id', $product->id)->delete();
$product->delete();
return response()
->json(['message' => 'Product deleted successfully'], Response::HTTP_OK);
}catch (\Exception $e){
\Log::channel('db_errors')->info('Record Deletion Error : Product -> '.$product->id);
\Log::channel('db_errors')->info($e->getMessage());
return response()
->json([
'message' => "Record not deleted.",
'errors' => ["error" => ["Unable to delete product."]]
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function cloneProduct(Product $product)
{
abort_if(Gate::denies('product_create'), Response::HTTP_FORBIDDEN, '403 Forbidden');
DB::beginTransaction();
try {
$cloned_product = $product->replicate();
$cloned_product->name = $cloned_product->name.' Clone';
$cloned_product->sku = $cloned_product->sku.'-clone'. time();
$cloned_product->slug = $cloned_product->slug.'-clone';
$cloned_product->is_draft = true;
$cloned_product->created_at = now();
$cloned_product->updated_at = now();
$cloned_product->save();
$this->cloneFeaturedImage($product, $cloned_product);
$this->duplicateVariations($product, $cloned_product);
$prices = $this->duplicateProductPrices($product, $cloned_product);
$variation_prices_ids = $this->duplicateProductVariationPriceRanges($product, $cloned_product, $prices);
$this->duplicateProductVariationCombinations($product, $cloned_product, $variation_prices_ids);
DB::commit();
return (new ProductResource($cloned_product))
->response()
->setStatusCode(Response::HTTP_CREATED);
} catch (\Exception $e){
\Log::channel('db_errors')->info('Product Clone Error');
\Log::channel('db_errors')->info($e->getMessage(). ' on line : '. $e->getLine());
return response()
->json([
'message' => "Can not clone product.",
'errors' => ["error" => ["Unable to clone product. (".$e->getMessage().")"]]
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function duplicateVariations($existing_product, $cloned_product)
{
$product_variations = ProductVariation::where('product_id', $existing_product->id)->get();
foreach ($product_variations as $product_variation) {
$clone_product_variation = $product_variation->replicate();
$clone_product_variation->product_id = $cloned_product->id;
$clone_product_variation->created_at = now();
$clone_product_variation->updated_at = now();
$clone_product_variation->save();
}
}
public function duplicateProductPrices($existing_product, $cloned_product)
{
$product_prices = ProductPrice::where('product_id', $existing_product->id)->get();
$price_ids = [];
foreach ($product_prices as $product_price) {
$clone_product_price = $product_price->replicate();
$clone_product_price->product_id = $cloned_product->id;
$clone_product_price->supplier_prod_number = $product_price->supplier_prod_number."-clone";
$clone_product_price->created_at = now();
$clone_product_price->updated_at = now();
$clone_product_price->save();
if ($product_price->product_sketch != null) {
$this->cloneSketch($product_price, $clone_product_price);
$product_price->save();
}
$price_ids[$product_price->id] = $clone_product_price->id;
}
return $price_ids;
}
public function duplicateProductVariationPriceRanges($existing_product, $cloned_product, $prices)
{
$product_variation_price_ranges = ProductVariationRange::where('product_id', $existing_product->id)->get();
$variation_price_ids = [];
foreach ($product_variation_price_ranges as $key => $product_variation_price_range) {
$clone_product_variation_price_range = $product_variation_price_range->replicate();
$clone_product_variation_price_range->product_id = $cloned_product->id;
$clone_product_variation_price_range->product_price_id = $prices[$product_variation_price_range->product_price_id];
$clone_product_variation_price_range->created_at = now();
$clone_product_variation_price_range->updated_at = now();
$clone_product_variation_price_range->save();
$variation_price_ids[$product_variation_price_range->product_price_id] = $clone_product_variation_price_range->product_price_id;
}
return $variation_price_ids;
}
public function duplicateProductVariationCombinations($existing_product, $cloned_product, $variation_price_ids)
{
$product_variation_combinations = ProductVariationCombination::where('product_id', $existing_product->id)->get();
foreach ($product_variation_combinations as $product_variation_combination) {
$clone_product_variation_combination = $product_variation_combination->replicate();
$clone_product_variation_combination->product_id = $cloned_product->id;
$clone_product_variation_combination->product_price_id = $variation_price_ids[$product_variation_combination->product_price_id];
$clone_product_variation_combination->created_at = now();
$clone_product_variation_combination->updated_at = now();
$clone_product_variation_combination->save();
}
}
public function cloneSketch($sourceModel, $destinationModel)
{
$sourceModelId = $sourceModel->id; // replace with the actual model ID
$destinationModelId = $destinationModel->id; // replace with the actual model ID
// Get the list of files in the source directory
$files = Storage::disk('variation')->files($sourceModelId);
// Iterate through the files and copy them to the destination directory
foreach ($files as $file) {
// Get the filename without the path
$filename = pathinfo($file, PATHINFO_BASENAME);
// Copy the file to the destination directory with the same filename
Storage::disk('variation')->copy(
"{$sourceModelId}/{$filename}",
"{$destinationModelId}/{$filename}"
);
}
$s = explode("/", $sourceModel->product_sketch);
if(isset($s[1])) {
$destinationModel->product_sketch = $destinationModel->id."/".$s[1];
$destinationModel->save();
}
}
public function cloneFeaturedImage($existing_product, $cloned_product)
{
$media = $existing_product->media->first();
$cloned_product->addMediaFromDisk($media->getPathRelativeToRoot(), 'product')
->preservingOriginal()
->toMediaCollection('product_featured_image', 'product');
}
public function deleteProduct(Product $product)
{
DB::beginTransaction();
try {
$orderItem = OrderItems::where('product_id', $product->id)->first();
if ($orderItem) {
return response()
->json([
'message' => "Can not delete product.",
'errors' => ["error" => ["This product is included in orders."]]
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
ProductVariation::where('product_id', $product->id)->delete();
ProductPrice::where('product_id', $product->id)->delete();
ProductVariationRange::where('product_id', $product->id)->delete();
ProductVariationCombination::where('product_id', $product->id)->delete();
$product->delete();
DB::commit();
return response()
->json(['message' => 'Product deleted successfully.'], Response::HTTP_OK);
} catch (\Exception $e){
\Log::channel('db_errors')->info('Product Delete Error');
\Log::channel('db_errors')->info($e->getMessage(). ' on line : '. $e->getLine());
return response()
->json([
'message' => "Can not delete product.",
'errors' => ["error" => ["Unable to delete product. (".$e->getMessage().")"]]
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function checkCombinationInOrder($priceId)
{
$orderItem = OrderItems::where('price_id', $priceId)->first();
if ($orderItem) {
return response()
->json([
'message' => "You cannot delete the combination as it is currently in use in certain orders.",
'success' => false,
], Response::HTTP_OK);
} else {
return response()
->json([
'message' => "Combination can be removed.",
'success' => true,
], Response::HTTP_OK);
}
}
}