Files
sam-api/app/Http/Controllers/Api/V1/ItemsBomController.php

177 lines
4.7 KiB
PHP
Raw Normal View History

<?php
namespace App\Http\Controllers\Api\V1;
use App\Helpers\ApiResponse;
use App\Http\Controllers\Controller;
use App\Models\Products\Product;
use App\Services\ProductBomService;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Items BOM Controller (ID-based)
*
* ID 기반으로 BOM을 관리하는 컨트롤러
* 내부적으로 기존 ProductBomService 재사용
*/
class ItemsBomController extends Controller
{
public function __construct(private ProductBomService $service) {}
/**
* GET /api/v1/items/{id}/bom
* BOM 라인 목록 조회 (flat list)
*/
public function index(int $id, Request $request)
{
return ApiResponse::handle(function () use ($id, $request) {
$this->validateProductExists($id);
return $this->service->index($id, $request->all());
}, __('message.bom.fetch'));
}
/**
* GET /api/v1/items/{id}/bom/tree
* BOM 트리 구조 조회 (계층적)
*/
public function tree(int $id, Request $request)
{
return ApiResponse::handle(function () use ($id, $request) {
$this->validateProductExists($id);
return $this->service->tree($request, $id);
}, __('message.bom.fetch'));
}
/**
* POST /api/v1/items/{id}/bom
* BOM 라인 추가 (bulk upsert)
*/
public function store(int $id, Request $request)
{
return ApiResponse::handle(function () use ($id, $request) {
$this->validateProductExists($id);
return $this->service->bulkUpsert($id, $request->input('items', []));
}, __('message.bom.created'));
}
/**
* PUT /api/v1/items/{id}/bom/{lineId}
* BOM 라인 수정
*/
public function update(int $id, int $lineId, Request $request)
{
return ApiResponse::handle(function () use ($id, $lineId, $request) {
$this->validateProductExists($id);
return $this->service->update($id, $lineId, $request->all());
}, __('message.bom.updated'));
}
/**
* DELETE /api/v1/items/{id}/bom/{lineId}
* BOM 라인 삭제
*/
public function destroy(int $id, int $lineId)
{
return ApiResponse::handle(function () use ($id, $lineId) {
$this->validateProductExists($id);
$this->service->destroy($id, $lineId);
return 'success';
}, __('message.bom.deleted'));
}
/**
* GET /api/v1/items/{id}/bom/summary
* BOM 요약 정보
*/
public function summary(int $id)
{
return ApiResponse::handle(function () use ($id) {
$this->validateProductExists($id);
return $this->service->summary($id);
}, __('message.bom.fetch'));
}
/**
* GET /api/v1/items/{id}/bom/validate
* BOM 유효성 검사
*/
public function validate(int $id)
{
return ApiResponse::handle(function () use ($id) {
$this->validateProductExists($id);
return $this->service->validateBom($id);
}, __('message.bom.fetch'));
}
/**
* POST /api/v1/items/{id}/bom/replace
* BOM 전체 교체
*/
public function replace(int $id, Request $request)
{
return ApiResponse::handle(function () use ($id, $request) {
$this->validateProductExists($id);
return $this->service->replaceBom($id, $request->all());
}, __('message.bom.created'));
}
/**
* POST /api/v1/items/{id}/bom/reorder
* BOM 정렬 변경
*/
public function reorder(int $id, Request $request)
{
return ApiResponse::handle(function () use ($id, $request) {
$this->validateProductExists($id);
$this->service->reorder($id, $request->input('items', []));
return 'success';
}, __('message.bom.reordered'));
}
/**
* GET /api/v1/items/{id}/bom/categories
* 해당 품목의 BOM에서 사용 중인 카테고리 목록
*/
public function listCategories(int $id)
{
return ApiResponse::handle(function () use ($id) {
$this->validateProductExists($id);
return $this->service->listCategoriesForProduct($id);
}, __('message.bom.fetch'));
}
// ==================== Helper Methods ====================
/**
* 품목 ID로 tenant 소유권 검증
*
* @throws NotFoundHttpException
*/
private function validateProductExists(int $id): void
{
$tenantId = app('tenant_id');
$exists = Product::query()
->where('tenant_id', $tenantId)
->where('id', $id)
->exists();
if (! $exists) {
throw new NotFoundHttpException(__('error.not_found'));
}
}
}