257 lines
9.0 KiB
PHP
257 lines
9.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\admin\product;
|
|
|
|
use App\Exports\ProductsExport;
|
|
use App\Imports\ProductsImport;
|
|
use App\Enums\Product\ProductTypeEnums;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Product\ProductRequest;
|
|
use App\Http\Services\ProductService;
|
|
use App\Repositories\Group\GroupRepositoryInterface;
|
|
use App\Repositories\Admin\Product\ProductRepositoryInterface;
|
|
use Illuminate\Http\Request;
|
|
use Maatwebsite\Excel\Facades\Excel;
|
|
use Yajra\DataTables\Facades\DataTables;
|
|
use Exception;
|
|
|
|
class ProductController extends Controller
|
|
{
|
|
public function __construct(
|
|
public GroupRepositoryInterface $groupRepository,
|
|
public ProductRepositoryInterface $productRepository,
|
|
public ProductService $productService
|
|
) {
|
|
parent::__construct();
|
|
}
|
|
|
|
public function index(Request $request)
|
|
{
|
|
$products = $this->productRepository->filter(
|
|
[
|
|
'page' => $request->get('page') ?? 1
|
|
]
|
|
);
|
|
|
|
$title = "List All Product";
|
|
|
|
return view('administrator.pages.product.index', compact('title', 'products'));
|
|
}
|
|
|
|
public function create(Request $request)
|
|
{
|
|
$step = $request->get('step') ?? 1;
|
|
$title = 'Add new product';
|
|
// Fetch Product Categories (Roots only, children via relation)
|
|
$group = \App\Models\ProductCategories::where('is_active', \App\Enums\Status::ACTIVE->value)->whereNull('parent_id')->get();
|
|
$type = null;
|
|
|
|
// Fetch OS versions with their group for the OS selector component
|
|
$osVersions = \App\Models\Os::with('osGroup')->where('status', 1)->get();
|
|
|
|
// Fetch Control Panels for Hosting products
|
|
$controlPanels = \App\Models\ControlPanel::active()->ordered()->get();
|
|
|
|
if ($step === 1) {
|
|
return view("administrator.pages.product.create", compact('group', 'type', 'title', 'osVersions', 'controlPanels'));
|
|
}
|
|
|
|
if (!$request->has(['step', 'type'])) {
|
|
return back()->withErrors('Missing step or type');
|
|
}
|
|
|
|
$type_id = (int) $request->type;
|
|
$product_name = $request->name;
|
|
|
|
$view = "administrator.pages.product.create";
|
|
|
|
$data = compact('type_id', 'title', 'group', 'type', 'product_name', 'osOptions');
|
|
|
|
return view($view, $data);
|
|
}
|
|
|
|
public function store(ProductRequest $request)
|
|
{
|
|
try {
|
|
$this->productService->store($request->validated());
|
|
|
|
return redirect()->route('products.index')->with('success', 'Add new product success');
|
|
} catch (Exception $e) {
|
|
return back()->withErrors($e->getMessage())->withInput();
|
|
}
|
|
}
|
|
|
|
public function edit(Request $request, $id)
|
|
{
|
|
$product = $this->productRepository->find($id);
|
|
|
|
if (!$product) {
|
|
return back()->withErrors("Can't find product.");
|
|
}
|
|
|
|
// Load relationships
|
|
$product->load(['pricings', 'osVersions', 'category']);
|
|
|
|
$title = 'Edit product: ' . $product->name;
|
|
$group = \App\Models\ProductCategories::where('is_active', \App\Enums\Status::ACTIVE->value)->whereNull('parent_id')->get();
|
|
$type = null;
|
|
|
|
// Fetch OS versions for select
|
|
$osVersions = \App\Models\Os::with('osGroup')->where('status', 1)->get();
|
|
|
|
$view = "administrator.pages.product.edit";
|
|
|
|
// Fetch Control Panels for Hosting products
|
|
$controlPanels = \App\Models\ControlPanel::active()->ordered()->get();
|
|
|
|
$data = compact('product', 'title', 'group', 'type', 'osVersions', 'controlPanels');
|
|
|
|
return view($view, $data);
|
|
}
|
|
|
|
public function update(ProductRequest $request, $id)
|
|
{
|
|
try {
|
|
$this->productService->update((int) $id, $request->validated());
|
|
return redirect()->route('products.index')->with('success', 'Update product success');
|
|
} catch (Exception $e) {
|
|
return back()->withErrors($e->getMessage())->withInput();
|
|
}
|
|
}
|
|
|
|
public function destroy(Request $request, $id)
|
|
{
|
|
try {
|
|
$this->productService->delete((int) $id);
|
|
return redirect()->route('products.index')->with('success', 'Deleted successfully');
|
|
} catch (Exception $e) {
|
|
return back()->withErrors($e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function duplicate($id)
|
|
{
|
|
try {
|
|
$product = $this->productRepository->find($id);
|
|
|
|
if (!$product) {
|
|
return back()->withErrors("Can't find product.");
|
|
}
|
|
|
|
$product->load(['pricings', 'osVersions', 'controlPanels']);
|
|
|
|
$newData = $product->only([
|
|
'short_description', 'description', 'setup_fee', 'trial_days',
|
|
'cpu', 'ram', 'gpu', 'disk', 'bandwidth', 'stock',
|
|
'is_unlimited', 'is_active', 'sort_order', 'product_type',
|
|
'product_categories_id', 'published_at',
|
|
]);
|
|
$newData['name'] = $product->name . ' (Copy)';
|
|
|
|
$newProduct = $this->productService->store($newData);
|
|
|
|
if ($product->osVersions->isNotEmpty()) {
|
|
$newProduct->osVersions()->sync($product->osVersions->pluck('id'));
|
|
}
|
|
|
|
if ($product->controlPanels->isNotEmpty()) {
|
|
$syncData = [];
|
|
foreach ($product->controlPanels as $panel) {
|
|
$syncData[$panel->id] = [
|
|
'price_modifier' => $panel->pivot->price_modifier,
|
|
'is_default' => $panel->pivot->is_default,
|
|
];
|
|
}
|
|
$newProduct->controlPanels()->sync($syncData);
|
|
}
|
|
|
|
if ($product->pricings->isNotEmpty()) {
|
|
foreach ($product->pricings as $pricing) {
|
|
$newProduct->pricings()->create([
|
|
'billing_cycle' => $pricing->billing_cycle,
|
|
'price' => $pricing->price,
|
|
'price_sale' => $pricing->price_sale,
|
|
'currency' => $pricing->currency,
|
|
'is_active' => $pricing->is_active,
|
|
]);
|
|
}
|
|
}
|
|
|
|
return redirect()->route('products.edit', ['id' => $newProduct->id])
|
|
->with('success', 'Product duplicated successfully');
|
|
} catch (Exception $e) {
|
|
return back()->withErrors($e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function datatable(Request $request)
|
|
{
|
|
$query = $this->productRepository->filter(
|
|
$request->all(),
|
|
['category', 'pricings'],
|
|
[],
|
|
['*'],
|
|
true
|
|
);
|
|
|
|
return DataTables::eloquent($query)
|
|
->addColumn('category', function ($d) {
|
|
return view('administrator.pages.product.datatable.category', ['row' => $d])->render();
|
|
})
|
|
->addColumn('price', function ($d) {
|
|
return view('administrator.pages.product.datatable.price', ['row' => $d])->render();
|
|
})
|
|
->addColumn('specs', function ($d) {
|
|
return view('administrator.pages.product.datatable.specs', ['row' => $d])->render();
|
|
})
|
|
->addColumn('status', function ($d) {
|
|
return view('administrator.pages.product.datatable.status', ['row' => $d])->render();
|
|
})
|
|
->addColumn('action', function ($d) {
|
|
return view('administrator.pages.product.datatable.action', ['row' => $d])->render();
|
|
})
|
|
->rawColumns(['category', 'price', 'specs', 'status', 'action'])
|
|
->make(true);
|
|
}
|
|
|
|
private function mapEnumToTypeId(?ProductTypeEnums $enum): int
|
|
{
|
|
return match ($enum) {
|
|
ProductTypeEnums::ADDON => 1,
|
|
ProductTypeEnums::DOMAIN => 2,
|
|
ProductTypeEnums::HOSTING => 3,
|
|
ProductTypeEnums::VPS => 4,
|
|
default => 0
|
|
};
|
|
}
|
|
|
|
public function export(Request $request)
|
|
{
|
|
if ($request->get('sample') == 1) {
|
|
return Excel::download(new ProductsExport(), 'products_sample.xlsx');
|
|
}
|
|
return Excel::download(new ProductsExport(), 'products_' . date('Y-m-d') . '.xlsx');
|
|
}
|
|
|
|
public function import(Request $request)
|
|
{
|
|
$request->validate([
|
|
'file' => 'required|mimes:xlsx,xls,csv'
|
|
]);
|
|
|
|
try {
|
|
Excel::import(new ProductsImport(), $request->file('file'));
|
|
return redirect()->route('products.index')->with('success', 'Import products successfully');
|
|
} catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
|
|
$failures = $e->failures();
|
|
$errorMessage = 'Import failed at row(s): ';
|
|
foreach ($failures as $failure) {
|
|
$errorMessage .= $failure->row() . ' (' . implode(', ', $failure->errors()) . '); ';
|
|
}
|
|
return back()->withErrors($errorMessage);
|
|
} catch (\Exception $e) {
|
|
return back()->withErrors('Import failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
}
|