Files
sam-manage/app/Http/Controllers/Api/Admin/ItemManagementApiController.php
김보곤 b469ae9bfc feat: [item-management] 수식 산출 결과를 FG BOM으로 저장하는 기능 추가
- 수식 산출 결과 합계 옆에 'BOM 저장' 버튼 추가
- 클릭 시 산출된 전체 품목을 FG의 bom JSON 필드에 저장
- 저장 후 자동으로 BOM 탭 전환 + 트리 표시
- POST /api/admin/items/{id}/save-bom 엔드포인트 추가
2026-03-18 15:33:00 +09:00

147 lines
4.4 KiB
PHP

<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Models\Items\Item;
use App\Services\FormulaApiService;
use App\Services\ItemManagementService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class ItemManagementApiController extends Controller
{
public function __construct(
private readonly ItemManagementService $service
) {}
/**
* 품목 목록 (HTML partial - 좌측 패널)
*/
public function index(Request $request): View
{
$items = $this->service->getItemList([
'search' => $request->input('search'),
'item_type' => $request->input('item_type'),
'per_page' => $request->input('per_page', 50),
]);
return view('item-management.partials.item-list', compact('items'));
}
/**
* BOM 재귀 트리 (JSON - 중앙 패널, JS 렌더링)
*/
public function bomTree(int $id, Request $request): JsonResponse
{
$maxDepth = $request->input('max_depth', 10);
$tree = $this->service->getBomTree($id, $maxDepth);
return response()->json($tree);
}
/**
* 품목 상세 (HTML partial - 우측 패널)
*/
public function detail(int $id): View
{
$data = $this->service->getItemDetail($id);
return view('item-management.partials.item-detail', [
'item' => $data['item'],
'bomChildren' => $data['bom_children'],
]);
}
/**
* 품목 삭제 (Soft Delete, 사용 중 체크)
*/
public function destroy(int $id): JsonResponse
{
$result = $this->service->deleteItem($id);
return response()->json($result, $result['success'] ? 200 : 422);
}
/**
* 품목 이력 조회 (audit_logs 기반)
*/
public function history(int $id): JsonResponse
{
$history = $this->service->getItemHistory($id);
return response()->json($history);
}
/**
* 절곡BOM 트리 (JSON - 중앙 패널)
* FG 품목 선택 시 해당 FG의 절곡 관련 BOM만, 미선택 시 전체 절곡 품목
*/
public function bendingBomTree(Request $request): JsonResponse
{
$itemId = $request->input('item_id') ? (int) $request->input('item_id') : null;
$tree = $this->service->getBendingBomTree($itemId);
return response()->json($tree);
}
/**
* 수식 산출 결과를 FG 품목의 BOM으로 저장
*/
public function saveBom(Request $request, int $id): JsonResponse
{
$request->validate([
'bom_items' => 'required|array|min:1',
'bom_items.*.child_item_id' => 'required|integer',
'bom_items.*.quantity' => 'required|numeric|min:0',
]);
$result = $this->service->saveBomFromFormula($id, $request->input('bom_items'));
return response()->json($result, $result['success'] ? 200 : 422);
}
/**
* 수식 기반 BOM 산출 (API 서버의 FormulaEvaluatorService HTTP 호출)
*/
public function calculateFormula(Request $request, int $id): JsonResponse
{
$item = Item::withoutGlobalScopes()
->where('tenant_id', session('selected_tenant_id'))
->findOrFail($id);
$width = (int) $request->input('width', 1000);
$height = (int) $request->input('height', 1000);
$qty = (int) $request->input('qty', 1);
$mp = $request->input('mp', 'single');
$variables = [
'W0' => $width,
'H0' => $height,
'QTY' => $qty,
'MP' => in_array($mp, ['single', 'three']) ? $mp : 'single',
];
// 제품모델/설치타입/마감타입 (입력값이 있으면 전달)
if ($request->filled('product_model')) {
$variables['product_model'] = $request->input('product_model');
}
if ($request->filled('installation_type')) {
$variables['installation_type'] = $request->input('installation_type');
}
if ($request->filled('finishing_type')) {
$variables['finishing_type'] = $request->input('finishing_type');
}
$formulaService = new FormulaApiService;
$result = $formulaService->calculateBom(
$item->code,
$variables,
(int) session('selected_tenant_id')
);
return response()->json($result);
}
}