refactor: CategoryField API를 SAM API Rules에 맞게 리팩토링
- FormRequest 패턴 적용 (CategoryFieldStoreRequest, CategoryFieldUpdateRequest)
- Service에서 Validator::make() 제거
- Controller 메시지 i18n 키로 변경 (__('message.category_field.*'))
- is_required 타입을 'Y'/'N' → boolean으로 통일
- Swagger 스키마 is_required boolean 타입으로 업데이트
- Model scopeRequired() boolean 조건으로 변경
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
use App\Helpers\ApiResponse;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\CategoryField\CategoryFieldStoreRequest;
|
||||
use App\Http\Requests\CategoryField\CategoryFieldUpdateRequest;
|
||||
use App\Services\CategoryFieldService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -16,15 +18,15 @@ public function index(int $id, Request $request)
|
||||
{
|
||||
return ApiResponse::handle(function () use ($id, $request) {
|
||||
return $this->service->index($id, $request->all());
|
||||
}, '카테고리 필드 목록');
|
||||
}, __('message.category_field.fetched'));
|
||||
}
|
||||
|
||||
// POST /categories/{id}/fields
|
||||
public function store(int $id, Request $request)
|
||||
public function store(int $id, CategoryFieldStoreRequest $request)
|
||||
{
|
||||
return ApiResponse::handle(function () use ($id, $request) {
|
||||
return $this->service->store($id, $request->all());
|
||||
}, '카테고리 필드 생성');
|
||||
return $this->service->store($id, $request->validated());
|
||||
}, __('message.category_field.created'));
|
||||
}
|
||||
|
||||
// GET /categories/fields/{field}
|
||||
@@ -32,15 +34,15 @@ public function show(int $field)
|
||||
{
|
||||
return ApiResponse::handle(function () use ($field) {
|
||||
return $this->service->show($field);
|
||||
}, '카테고리 필드 조회');
|
||||
}, __('message.category_field.fetched'));
|
||||
}
|
||||
|
||||
// PATCH /categories/fields/{field}
|
||||
public function update(int $field, Request $request)
|
||||
public function update(int $field, CategoryFieldUpdateRequest $request)
|
||||
{
|
||||
return ApiResponse::handle(function () use ($field, $request) {
|
||||
return $this->service->update($field, $request->all());
|
||||
}, '카테고리 필드 수정');
|
||||
return $this->service->update($field, $request->validated());
|
||||
}, __('message.category_field.updated'));
|
||||
}
|
||||
|
||||
// DELETE /categories/fields/{field}
|
||||
@@ -50,7 +52,7 @@ public function destroy(int $field)
|
||||
$this->service->destroy($field);
|
||||
|
||||
return 'success';
|
||||
}, '카테고리 필드 삭제');
|
||||
}, __('message.category_field.deleted'));
|
||||
}
|
||||
|
||||
// POST /categories/{id}/fields/reorder
|
||||
@@ -60,7 +62,7 @@ public function reorder(int $id, Request $request)
|
||||
$this->service->reorder($id, $request->input());
|
||||
|
||||
return 'success';
|
||||
}, '카테고리 필드 정렬 저장');
|
||||
}, __('message.category_field.reordered'));
|
||||
}
|
||||
|
||||
// PUT /categories/{id}/fields/bulk-upsert
|
||||
@@ -68,6 +70,6 @@ public function bulkUpsert(int $id, Request $request)
|
||||
{
|
||||
return ApiResponse::handle(function () use ($id, $request) {
|
||||
return $this->service->bulkUpsert($id, $request->input('items', []));
|
||||
}, '카테고리 필드 일괄 업서트');
|
||||
}, __('message.category_field.bulk_upsert'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\CategoryField;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CategoryFieldStoreRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'field_key' => 'required|string|max:30|alpha_dash',
|
||||
'field_name' => 'required|string|max:100',
|
||||
'field_type' => 'required|string|max:20',
|
||||
'is_required' => 'nullable|boolean',
|
||||
'sort_order' => 'nullable|integer|min:0',
|
||||
'default_value' => 'nullable|string|max:100',
|
||||
'options' => 'nullable|json',
|
||||
'description' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\CategoryField;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CategoryFieldUpdateRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'field_key' => 'sometimes|string|max:30|alpha_dash',
|
||||
'field_name' => 'sometimes|string|max:100',
|
||||
'field_type' => 'sometimes|string|max:20',
|
||||
'is_required' => 'sometimes|boolean',
|
||||
'sort_order' => 'sometimes|integer|min:0',
|
||||
'default_value' => 'nullable|string|max:100',
|
||||
'options' => 'nullable|json',
|
||||
'description' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,6 @@ public function category()
|
||||
// 편의 스코프
|
||||
public function scopeRequired($q)
|
||||
{
|
||||
return $q->where('is_required', 1);
|
||||
return $q->where('is_required', true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
use App\Models\Commons\Category;
|
||||
use App\Models\Commons\CategoryField;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator; // 가정: Eloquent 모델 경로
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class CategoryFieldService extends Service
|
||||
@@ -32,31 +31,22 @@ public function store(int $categoryId, array $data)
|
||||
|
||||
$this->assertCategoryExists($tenantId, $categoryId);
|
||||
|
||||
$v = Validator::make($data, [
|
||||
'field_key' => 'required|string|max:30|alpha_dash',
|
||||
'field_name' => 'required|string|max:100',
|
||||
'field_type' => 'required|string|max:20',
|
||||
'is_required' => 'nullable|in:Y,N',
|
||||
'sort_order' => 'nullable|integer|min:0',
|
||||
'default_value' => 'nullable|string|max:100',
|
||||
'options' => 'nullable|json',
|
||||
'description' => 'nullable|string|max:255',
|
||||
]);
|
||||
$payload = $v->validate();
|
||||
// FormRequest에서 이미 검증됨
|
||||
$payload = $data;
|
||||
|
||||
// 카테고리 내 field_key 유니크 검증
|
||||
$exists = CategoryField::query()
|
||||
->where(compact('tenant_id'))
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('category_id', $categoryId)
|
||||
->where('field_key', $payload['field_key'])
|
||||
->exists();
|
||||
if ($exists) {
|
||||
throw new BadRequestHttpException(__('error.duplicate_key')); // ko/error.php에 매핑
|
||||
throw new BadRequestHttpException(__('error.duplicate_key'));
|
||||
}
|
||||
|
||||
$payload['tenant_id'] = $tenantId;
|
||||
$payload['category_id'] = $categoryId;
|
||||
$payload['is_required'] = $payload['is_required'] ?? 'N';
|
||||
$payload['is_required'] = $payload['is_required'] ?? false;
|
||||
$payload['sort_order'] = $payload['sort_order'] ?? 0;
|
||||
$payload['created_by'] = $userId;
|
||||
|
||||
@@ -91,17 +81,8 @@ public function update(int $fieldId, array $data)
|
||||
throw new BadRequestHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
$v = Validator::make($data, [
|
||||
'field_key' => 'sometimes|string|max:30|alpha_dash',
|
||||
'field_name' => 'sometimes|string|max:100',
|
||||
'field_type' => 'sometimes|string|max:20',
|
||||
'is_required' => 'sometimes|in:Y,N',
|
||||
'sort_order' => 'sometimes|integer|min:0',
|
||||
'default_value' => 'nullable|string|max:100',
|
||||
'options' => 'nullable|json',
|
||||
'description' => 'nullable|string|max:255',
|
||||
]);
|
||||
$payload = $v->validate();
|
||||
// FormRequest에서 이미 검증됨
|
||||
$payload = $data;
|
||||
|
||||
if (isset($payload['field_key']) && $payload['field_key'] !== $field->field_key) {
|
||||
$dup = CategoryField::query()
|
||||
@@ -170,19 +151,11 @@ public function bulkUpsert(int $categoryId, array $items): array
|
||||
$result = ['created' => 0, 'updated' => 0];
|
||||
|
||||
DB::transaction(function () use ($tenantId, $userId, $categoryId, $items, &$result) {
|
||||
foreach ($items as $it) {
|
||||
$v = Validator::make($it, [
|
||||
'id' => 'nullable|integer',
|
||||
'field_key' => 'sometimes|required_without:id|string|max:30|alpha_dash',
|
||||
'field_name' => 'required|string|max:100',
|
||||
'field_type' => 'required|string|max:20',
|
||||
'is_required' => 'nullable|in:Y,N',
|
||||
'sort_order' => 'nullable|integer|min:0',
|
||||
'default_value' => 'nullable|string|max:100',
|
||||
'options' => 'nullable|json',
|
||||
'description' => 'nullable|string|max:255',
|
||||
]);
|
||||
$payload = $v->validate();
|
||||
foreach ($items as $payload) {
|
||||
// 기본적인 검증 (FormRequest가 배열 내부까지는 검증 못함)
|
||||
if (! isset($payload['field_name'], $payload['field_type'])) {
|
||||
throw new BadRequestHttpException(__('error.invalid_payload'));
|
||||
}
|
||||
|
||||
if (! empty($payload['id'])) {
|
||||
$model = CategoryField::query()
|
||||
@@ -224,7 +197,7 @@ public function bulkUpsert(int $categoryId, array $items): array
|
||||
|
||||
$payload['tenant_id'] = $tenantId;
|
||||
$payload['category_id'] = $categoryId;
|
||||
$payload['is_required'] = $payload['is_required'] ?? 'N';
|
||||
$payload['is_required'] = $payload['is_required'] ?? false;
|
||||
$payload['sort_order'] = $payload['sort_order'] ?? 0;
|
||||
$payload['created_by'] = $userId;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* @OA\Property(property="field_key", type="string", example="width"),
|
||||
* @OA\Property(property="field_name", type="string", example="폭(mm)"),
|
||||
* @OA\Property(property="field_type", type="string", example="number"),
|
||||
* @OA\Property(property="is_required", type="string", enum={"Y","N"}, example="N"),
|
||||
* @OA\Property(property="is_required", type="boolean", example=false),
|
||||
* @OA\Property(property="sort_order", type="integer", example=1),
|
||||
* @OA\Property(property="default_value", type="string", nullable=true, example=null),
|
||||
* @OA\Property(
|
||||
|
||||
@@ -65,6 +65,15 @@
|
||||
'template_applied' => '카테고리 템플릿이 적용되었습니다.',
|
||||
],
|
||||
|
||||
'category_field' => [
|
||||
'fetched' => '카테고리 필드를 조회했습니다.',
|
||||
'created' => '카테고리 필드가 생성되었습니다.',
|
||||
'updated' => '카테고리 필드가 수정되었습니다.',
|
||||
'deleted' => '카테고리 필드가 삭제되었습니다.',
|
||||
'reordered' => '카테고리 필드 정렬이 변경되었습니다.',
|
||||
'bulk_upsert' => '카테고리 필드가 일괄 저장되었습니다.',
|
||||
],
|
||||
|
||||
'design' => [
|
||||
'template_cloned' => 'BOM 템플릿이 복제되었습니다.',
|
||||
'template_diff' => 'BOM 템플릿 차이를 계산했습니다.',
|
||||
|
||||
Reference in New Issue
Block a user