fix : 카테고리, 제품등록, BOM등록 API (일부 개발 - BOM 추가 작업 필요)
This commit is contained in:
@@ -3,8 +3,12 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Products\CommonCode;
|
||||
use App\Models\Products\Product;
|
||||
use App\Models\Commons\Category;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class ProductService
|
||||
class ProductService extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -24,16 +28,27 @@ public static function getCategory($request)
|
||||
/**
|
||||
* 내부 재귀 함수 (하위 카테고리 트리 구조로 구성)
|
||||
*/
|
||||
protected static function fetchCategoryTree($parentId = null, $group = 'category')
|
||||
protected function fetchCategoryTree(?int $parentId = null)
|
||||
{
|
||||
$categories = CommonCode::where('code_group', 'category')
|
||||
->where('parent_id', $parentId)
|
||||
->orderBy('sort_order')->debug();
|
||||
$categories = $categories->get();
|
||||
$tenantId = $this->tenantId(); // Base Service에서 상속받은 메서드
|
||||
|
||||
$query = Category::query()
|
||||
->when($tenantId, fn($q) => $q->where('tenant_id', $tenantId))
|
||||
->when(
|
||||
is_null($parentId),
|
||||
fn($q) => $q->whereNull('parent_id'),
|
||||
fn($q) => $q->where('parent_id', $parentId)
|
||||
)
|
||||
->where('is_active', 1)
|
||||
->orderBy('sort_order');
|
||||
|
||||
$categories = $query->get();
|
||||
|
||||
foreach ($categories as $category) {
|
||||
$category->children = self::fetchCategoryTree($category->id);
|
||||
$children = $this->fetchCategoryTree($category->id);
|
||||
$category->setRelation('children', $children);
|
||||
}
|
||||
|
||||
return $categories;
|
||||
}
|
||||
|
||||
@@ -46,5 +61,157 @@ public static function getCategoryFlat($group = 'category')
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
// 목록/검색
|
||||
public function index(array $params)
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
|
||||
$size = (int)($params['size'] ?? 20);
|
||||
$q = trim((string)($params['q'] ?? ''));
|
||||
$categoryId = $params['category_id'] ?? null;
|
||||
$productType = $params['product_type'] ?? null; // PRODUCT|PART|SUBASSEMBLY...
|
||||
$active = $params['active'] ?? null; // 1/0
|
||||
|
||||
$query = Product::query()->where('tenant_id', $tenantId);
|
||||
|
||||
if ($q !== '') {
|
||||
$query->where(function ($w) use ($q) {
|
||||
$w->where('name', 'like', "%{$q}%")
|
||||
->orWhere('code', 'like', "%{$q}%")
|
||||
->orWhere('description', 'like', "%{$q}%");
|
||||
});
|
||||
}
|
||||
if ($categoryId) $query->where('category_id', (int)$categoryId);
|
||||
if ($productType) $query->where('product_type', $productType);
|
||||
if ($active !== null && $active !== '') $query->where('is_active', (int)$active);
|
||||
|
||||
return $query->orderByDesc('id')->paginate($size);
|
||||
}
|
||||
|
||||
// 생성
|
||||
public function store(array $data)
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$v = Validator::make($data, [
|
||||
'code' => 'required|string|max:30',
|
||||
'name' => 'required|string|max:100',
|
||||
'category_id' => 'required|integer',
|
||||
'product_type' => 'required|string|max:30',
|
||||
'attributes' => 'nullable|array',
|
||||
'description' => 'nullable|string|max:255',
|
||||
'is_sellable' => 'nullable|in:0,1',
|
||||
'is_purchasable' => 'nullable|in:0,1',
|
||||
'is_producible' => 'nullable|in:0,1',
|
||||
'is_active' => 'nullable|in:0,1',
|
||||
]);
|
||||
$payload = $v->validate();
|
||||
|
||||
// tenant별 code 유니크 수동 체크(운영 전 DB 유니크 구성도 권장)
|
||||
$dup = Product::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', $payload['code'])
|
||||
->exists();
|
||||
if ($dup) throw new BadRequestHttpException(__('error.duplicate_key'));
|
||||
|
||||
$payload['tenant_id'] = $tenantId;
|
||||
$payload['created_by'] = $userId;
|
||||
$payload['is_sellable'] = $payload['is_sellable'] ?? 1;
|
||||
$payload['is_purchasable'] = $payload['is_purchasable'] ?? 0;
|
||||
$payload['is_producible'] = $payload['is_producible'] ?? 1;
|
||||
$payload['is_active'] = $payload['is_active'] ?? 1;
|
||||
|
||||
// attributes array → json 저장 (Eloquent casts가 array면 그대로 가능)
|
||||
return Product::create($payload);
|
||||
}
|
||||
|
||||
// 단건
|
||||
public function show(int $id)
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$p = Product::query()->where('tenant_id', $tenantId)->find($id);
|
||||
if (!$p) throw new BadRequestHttpException(__('error.not_found'));
|
||||
return $p;
|
||||
}
|
||||
|
||||
// 수정
|
||||
public function update(int $id, array $data)
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$p = Product::query()->where('tenant_id', $tenantId)->find($id);
|
||||
if (!$p) throw new BadRequestHttpException(__('error.not_found'));
|
||||
|
||||
$v = Validator::make($data, [
|
||||
'code' => 'sometimes|string|max:30',
|
||||
'name' => 'sometimes|string|max:100',
|
||||
'category_id' => 'sometimes|integer',
|
||||
'product_type' => 'sometimes|string|max:30',
|
||||
'attributes' => 'nullable|array',
|
||||
'description' => 'nullable|string|max:255',
|
||||
'is_sellable' => 'nullable|in:0,1',
|
||||
'is_purchasable' => 'nullable|in:0,1',
|
||||
'is_producible' => 'nullable|in:0,1',
|
||||
'is_active' => 'nullable|in:0,1',
|
||||
]);
|
||||
$payload = $v->validate();
|
||||
|
||||
if (isset($payload['code']) && $payload['code'] !== $p->code) {
|
||||
$dup = Product::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', $payload['code'])
|
||||
->exists();
|
||||
if ($dup) throw new BadRequestHttpException(__('error.duplicate_key'));
|
||||
}
|
||||
|
||||
$payload['updated_by'] = $userId;
|
||||
$p->update($payload);
|
||||
return $p->refresh();
|
||||
}
|
||||
|
||||
// 삭제(soft)
|
||||
public function destroy(int $id): void
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$p = Product::query()->where('tenant_id', $tenantId)->find($id);
|
||||
if (!$p) throw new BadRequestHttpException(__('error.not_found'));
|
||||
$p->delete();
|
||||
}
|
||||
|
||||
// 간편 검색(모달/드롭다운)
|
||||
public function search(array $params)
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$q = trim((string)($params['q'] ?? ''));
|
||||
$lim = (int)($params['limit'] ?? 20);
|
||||
|
||||
$qr = Product::query()->where('tenant_id', $tenantId);
|
||||
if ($q !== '') {
|
||||
$qr->where(function ($w) use ($q) {
|
||||
$w->where('name', 'like', "%{$q}%")
|
||||
->orWhere('code', 'like', "%{$q}%");
|
||||
});
|
||||
}
|
||||
return $qr->orderBy('name')->limit($lim)->get(['id','code','name','product_type','category_id','is_active']);
|
||||
}
|
||||
|
||||
// 활성 토글
|
||||
public function toggle(int $id)
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$p = Product::query()->where('tenant_id', $tenantId)->find($id);
|
||||
if (!$p) throw new BadRequestHttpException(__('error.not_found'));
|
||||
|
||||
$p->is_active = $p->is_active ? 0 : 1;
|
||||
$p->updated_by = $userId;
|
||||
$p->save();
|
||||
|
||||
return ['id' => $p->id, 'is_active' => (int)$p->is_active];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user