diff --git a/app/Http/Controllers/Api/V1/Design/DesignModelController.php b/app/Http/Controllers/Api/V1/Design/DesignModelController.php index 2c16a31..470f786 100644 --- a/app/Http/Controllers/Api/V1/Design/DesignModelController.php +++ b/app/Http/Controllers/Api/V1/Design/DesignModelController.php @@ -5,7 +5,9 @@ use App\Helpers\ApiResponse; use App\Http\Controllers\Controller; use App\Services\Design\ModelService; -use Illuminate\Http\Request; +use App\Http\Requests\Common\PaginateRequest; +use App\Http\Requests\Design\Model\StoreRequest; +use App\Http\Requests\Design\Model\UpdateRequest; class DesignModelController extends Controller { @@ -13,48 +15,35 @@ public function __construct( protected ModelService $service ) {} - public function index(Request $request) + public function index(PaginateRequest $request) { return ApiResponse::handle(function () use ($request) { - $q = $request->query('q', ''); - $page = (int) $request->query('page', 1); - $size = (int) $request->query('size', 20); + $p = $request->validatedOrDefaults(); + $q = $p['q'] ?? ''; + $page = (int) $p['page']; + $size = (int) $p['size']; + + // 현재 서비스 시그니처가 list($q, $page, $size)이므로 정합 유지 return $this->service->list($q, $page, $size); }, __('message.fetched')); } - public function store(Request $request) + public function store(StoreRequest $request) { return ApiResponse::handle(function () use ($request) { - $payload = $request->validate([ - 'code' => 'required|string|max:100', - 'name' => 'required|string|max:200', - 'category_id' => 'nullable|integer', - 'lifecycle' => 'nullable|string|max:30', - 'description' => 'nullable|string', - 'is_active' => 'boolean', - ]); - return $this->service->create($payload); + return $this->service->create($request->validated()); }, __('message.created')); } public function show(int $id) { - return ApiResponse::handle(fn() => $this->service->find($id), __('message.fetched')); + return ApiResponse::handle(fn () => $this->service->find($id), __('message.fetched')); } - public function update(Request $request, int $id) + public function update(UpdateRequest $request, int $id) { return ApiResponse::handle(function () use ($request, $id) { - $payload = $request->validate([ - 'code' => 'sometimes|string|max:100', - 'name' => 'sometimes|string|max:200', - 'category_id' => 'nullable|integer', - 'lifecycle' => 'nullable|string|max:30', - 'description' => 'nullable|string', - 'is_active' => 'boolean', - ]); - return $this->service->update($id, $payload); + return $this->service->update($id, $request->validated()); }, __('message.updated')); } diff --git a/app/Http/Requests/Common/PaginateRequest.php b/app/Http/Requests/Common/PaginateRequest.php new file mode 100644 index 0000000..28e8024 --- /dev/null +++ b/app/Http/Requests/Common/PaginateRequest.php @@ -0,0 +1,29 @@ + 'nullable|integer|min:1', + 'size' => 'nullable|integer|min:1|max:100', + 'q' => 'nullable|string|max:100', + 'sort' => 'nullable|string|in:id,code,name,created_at', + 'order' => 'nullable|string|in:asc,desc', + ]; + } + + public function validatedOrDefaults(): array + { + $v = $this->validated(); + $v['page'] = $v['page'] ?? 1; + $v['size'] = $v['size'] ?? 20; + $v['order'] = $v['order'] ?? 'desc'; + return $v; + } +} diff --git a/app/Http/Requests/Design/BomTemplate/ReplaceItemsRequest.php b/app/Http/Requests/Design/BomTemplate/ReplaceItemsRequest.php new file mode 100644 index 0000000..ec90832 --- /dev/null +++ b/app/Http/Requests/Design/BomTemplate/ReplaceItemsRequest.php @@ -0,0 +1,28 @@ +mapWithKeys(fn($rule, $key) => ["items.*.$key" => $rule]) + ->all(); + + return ['items' => 'required|array|min:1'] + $itemRules; + } + + public function messages(): array + { + return [ + 'items.required' => __('validation.required', ['attribute' => 'items']), + 'items.array' => __('validation.array', ['attribute' => 'items']), + 'items.min' => __('validation.min.array', ['attribute' => 'items', 'min' => 1]), + ]; + } +} diff --git a/app/Http/Requests/Design/BomTemplate/UpsertRequest.php b/app/Http/Requests/Design/BomTemplate/UpsertRequest.php new file mode 100644 index 0000000..1a73904 --- /dev/null +++ b/app/Http/Requests/Design/BomTemplate/UpsertRequest.php @@ -0,0 +1,22 @@ + 'required|string|max:100', + 'is_primary' => 'nullable|boolean', + 'notes' => 'nullable|string', + ]; + } +} diff --git a/app/Http/Requests/Design/Model/StoreRequest.php b/app/Http/Requests/Design/Model/StoreRequest.php new file mode 100644 index 0000000..37a70f6 --- /dev/null +++ b/app/Http/Requests/Design/Model/StoreRequest.php @@ -0,0 +1,36 @@ + 'required|string|max:100', + 'name' => 'required|string|max:200', + 'category_id' => 'nullable|integer', + 'lifecycle' => 'nullable|string|max:50', + 'description' => 'nullable|string', + 'is_active' => 'boolean', + ]; + } + + public function messages(): array + { + return [ + 'code.required' => __('validation.required', ['attribute' => '모델코드']), + 'name.required' => __('validation.required', ['attribute' => '모델명']), + ]; + } + + protected function prepareForValidation(): void + { + if ($this->has('code')) { + $this->merge(['code' => trim($this->input('code'))]); + } + } +} diff --git a/app/Http/Requests/Design/Model/UpdateRequest.php b/app/Http/Requests/Design/Model/UpdateRequest.php new file mode 100644 index 0000000..f9b403b --- /dev/null +++ b/app/Http/Requests/Design/Model/UpdateRequest.php @@ -0,0 +1,25 @@ + 'sometimes|string|max:100', + 'name' => 'sometimes|string|max:200', + 'category_id' => 'nullable|integer', + 'lifecycle' => 'nullable|string|max:50', + 'description' => 'nullable|string', + 'is_active' => 'boolean', + ]; + } +} diff --git a/app/Http/Requests/Design/ModelVersion/CreateDraftRequest.php b/app/Http/Requests/Design/ModelVersion/CreateDraftRequest.php new file mode 100644 index 0000000..c345b57 --- /dev/null +++ b/app/Http/Requests/Design/ModelVersion/CreateDraftRequest.php @@ -0,0 +1,30 @@ + 'nullable|integer|min:1', + 'notes' => 'nullable|string', + 'effective_from' => 'nullable|date', + 'effective_to' => 'nullable|date|after_or_equal:effective_from', + ]; + } + + public function messages(): array + { + return [ + 'effective_to.after_or_equal' => __('validation.after_or_equal', ['attribute' => 'effective_to', 'date' => 'effective_from']), + ]; + } +} diff --git a/app/Support/Validation/BomItemRules.php b/app/Support/Validation/BomItemRules.php new file mode 100644 index 0000000..42d31d3 --- /dev/null +++ b/app/Support/Validation/BomItemRules.php @@ -0,0 +1,19 @@ + 'required|string|in:MATERIAL,PRODUCT', + 'ref_id' => 'required|integer|min:1', + 'qty' => 'required|numeric|gt:0', + 'waste_rate' => 'nullable|numeric|min:0', + 'uom_id' => 'nullable|integer|min:1', + 'notes' => 'nullable|string|max:255', + 'sort_order' => 'nullable|integer', + 'category_id'=> 'nullable|integer', // 선택: 카테고리 분류 사용 시 + ]; + } +} diff --git a/storage/api-docs/api-docs.json b/storage/api-docs/api-docs.json old mode 100644 new mode 100755