164 lines
5.9 KiB
PHP
164 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use App\Models\Product;
|
|
use App\Services\StockService;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
class ProductController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'search' => ['nullable', 'string', 'max:255'],
|
|
'sort' => ['nullable', Rule::in(['name', 'quantity'])],
|
|
'order' => ['nullable', Rule::in(['asc', 'desc'])],
|
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:200'],
|
|
]);
|
|
|
|
$search = $validated['search'] ?? null;
|
|
$sort = $validated['sort'] ?? 'name';
|
|
$order = $validated['order'] ?? 'asc';
|
|
$perPage = $validated['per_page'] ?? 2;
|
|
// dd($search);
|
|
|
|
$title = '상품목록';
|
|
$products = Product::searchkeyword($search, $sort, $order, $perPage);
|
|
return view('product.list', compact('title', 'products'));
|
|
}
|
|
public function input()
|
|
{
|
|
$title = '상품추가';
|
|
$categories = \App\Models\Category::orderBy('name')->get();
|
|
return view('product.input', compact('title', 'categories'));
|
|
}
|
|
|
|
public function edit(Product $product)
|
|
{
|
|
$title = '상품수정';
|
|
$categories = \App\Models\Category::orderBy('name')->get();
|
|
return view('product.edit', compact('product', 'title', 'categories'));
|
|
}
|
|
|
|
public function update(Request $request, Product $product)
|
|
{
|
|
// 1) 입력 값 검증
|
|
$data = $request->validate([
|
|
'name' => ['required', 'string'],
|
|
'sku' => [
|
|
'required',
|
|
'string',
|
|
Rule::unique('products', 'sku')->ignore($product->id), // 현재 상품은 예외
|
|
],
|
|
'price' => ['required', 'numeric', 'min:0'],
|
|
'image' => ['nullable', 'image', 'mimes:jpg,jpeg,png,webp', 'max:2048'],
|
|
]);
|
|
|
|
// 2) 텍스트 데이터 업데이트
|
|
$product->name = $data['name'];
|
|
$product->sku = $data['sku'];
|
|
$product->price = $data['price'];
|
|
|
|
// 3) 이미지 처리
|
|
if ($request->hasFile('image')) {
|
|
|
|
// 기존 이미지가 있으면 삭제
|
|
if ($product->image && Storage::disk('public')->exists($product->image)) {
|
|
Storage::disk('public')->delete($product->image);
|
|
// Storage 파사드를 이용하면, 저장소 드라이버가 바뀌어도 코드 수정 최소화
|
|
}
|
|
|
|
// 새 이미지 저장
|
|
$path = $request->file('image')->store('uploads', 'public');
|
|
$product->image = $path;
|
|
}
|
|
|
|
// 4) 저장
|
|
$product->save();
|
|
|
|
// 5) 결과 응답
|
|
return redirect()
|
|
->route('product')
|
|
->with('success', '상품정보가 수정되었습니다.');
|
|
}
|
|
|
|
public function destroy($id)
|
|
{
|
|
// 1. 모델을 먼저 가져온다
|
|
$product = Product::findOrFail($id);
|
|
|
|
// 2. 이미지가 있는 경우만 삭제
|
|
if (!empty($product->image)) {
|
|
Storage::disk('public')->delete($product->image);
|
|
}
|
|
|
|
// 3. DB 레코드 삭제
|
|
$product->delete();
|
|
|
|
// 4. 목록으로 이동
|
|
return redirect()
|
|
->route('product')
|
|
->with('success', '상품이 삭제되었습니다.');
|
|
}
|
|
|
|
public function store(Request $request, StockService $stock)
|
|
{
|
|
// 1) 입력 값 검증 (배열 형태)
|
|
$data = $request->validate([
|
|
'products' => ['required', 'array', 'min:1'],
|
|
'products.*.category' => ['nullable', 'string', 'max:50'],
|
|
'products.*.name' => ['required', 'string', 'max:100'],
|
|
'products.*.sku' => ['required', 'string', 'max:255', 'distinct', 'unique:products,sku'], // distinct: 요청 내 중복 체크
|
|
'products.*.manufacturer'=>['nullable', 'string', 'max:100'],
|
|
'products.*.price' => ['required', 'numeric', 'min:0'],
|
|
'products.*.quantity' => ['nullable', 'numeric', 'min:0'],
|
|
'products.*.image' => ['nullable', 'image', 'max:2048'],
|
|
], [
|
|
'products.*.name.required' => '상품명은 필수입니다.',
|
|
'products.*.sku.required' => 'SKU는 필수입니다.',
|
|
'products.*.sku.unique' => '이미 등록된 SKU가 존재합니다.',
|
|
'products.*.sku.distinct' => '입력된 상품 중 중복된 SKU가 있습니다.',
|
|
'products.*.price.required' => '가격은 필수입니다.',
|
|
]);
|
|
|
|
$savedCount = 0;
|
|
|
|
foreach ($data['products'] as $key => $item) {
|
|
// 2) 상품 데이터 준비
|
|
$productData = [
|
|
'category' => $item['category'] ?? null,
|
|
'name' => $item['name'],
|
|
'sku' => $item['sku'],
|
|
'manufacturer' => $item['manufacturer'] ?? null,
|
|
'price' => $item['price'],
|
|
'quantity' => 0, // 초기 재고 0
|
|
];
|
|
|
|
// 3) 이미지 처리 (배열 인덱스 매칭)
|
|
if ($request->hasFile("products.{$key}.image")) {
|
|
$productData['image'] = $request
|
|
->file("products.{$key}.image")
|
|
->store('products', 'public');
|
|
}
|
|
|
|
// 4) 상품 생성
|
|
$product = Product::create($productData);
|
|
$savedCount++;
|
|
|
|
// 5) 초기 재고 입고 처리
|
|
$initialQty = isset($item['quantity']) ? (int) $item['quantity'] : 0;
|
|
if ($initialQty > 0) {
|
|
$stock->setInitialStock($product, $initialQty);
|
|
}
|
|
}
|
|
|
|
// 6) 결과 응답
|
|
return redirect()
|
|
->route('product')
|
|
->with('success', $savedCount . '개의 상품이 등록되었습니다.');
|
|
}
|
|
}
|