Files
sam-api/app/Services/CategoryFieldService.php
hskwon d4e9f2a6e4 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 조건으로 변경
2025-11-14 13:45:54 +09:00

224 lines
7.6 KiB
PHP

<?php
namespace App\Services;
use App\Models\Commons\Category;
use App\Models\Commons\CategoryField;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class CategoryFieldService extends Service
{
public function index(int $categoryId, array $params)
{
$tenantId = $this->tenantId();
$size = (int) ($params['size'] ?? 20);
$sort = $params['sort'] ?? 'sort_order';
$order = strtolower($params['order'] ?? 'asc') === 'desc' ? 'desc' : 'asc';
return CategoryField::query()
->where('tenant_id', $tenantId)
->where('category_id', $categoryId)
->orderBy($sort, $order)
->paginate($size);
}
public function store(int $categoryId, array $data)
{
$tenantId = $this->tenantId();
$userId = $this->apiUserId();
$this->assertCategoryExists($tenantId, $categoryId);
// FormRequest에서 이미 검증됨
$payload = $data;
// 카테고리 내 field_key 유니크 검증
$exists = CategoryField::query()
->where('tenant_id', $tenantId)
->where('category_id', $categoryId)
->where('field_key', $payload['field_key'])
->exists();
if ($exists) {
throw new BadRequestHttpException(__('error.duplicate_key'));
}
$payload['tenant_id'] = $tenantId;
$payload['category_id'] = $categoryId;
$payload['is_required'] = $payload['is_required'] ?? false;
$payload['sort_order'] = $payload['sort_order'] ?? 0;
$payload['created_by'] = $userId;
return CategoryField::create($payload);
}
public function show(int $fieldId)
{
$tenantId = $this->tenantId();
$field = CategoryField::query()
->where('tenant_id', $tenantId)
->find($fieldId);
if (! $field) {
throw new BadRequestHttpException(__('error.not_found'));
}
return $field;
}
public function update(int $fieldId, array $data)
{
$tenantId = $this->tenantId();
$userId = $this->apiUserId();
$field = CategoryField::query()
->where('tenant_id', $tenantId)
->find($fieldId);
if (! $field) {
throw new BadRequestHttpException(__('error.not_found'));
}
// FormRequest에서 이미 검증됨
$payload = $data;
if (isset($payload['field_key']) && $payload['field_key'] !== $field->field_key) {
$dup = CategoryField::query()
->where('tenant_id', $tenantId)
->where('category_id', $field->category_id)
->where('field_key', $payload['field_key'])
->exists();
if ($dup) {
throw new BadRequestHttpException(__('error.duplicate_key'));
}
}
$payload['updated_by'] = $userId;
$field->update($payload);
return $field->refresh();
}
public function destroy(int $fieldId): void
{
$tenantId = $this->tenantId();
$field = CategoryField::query()
->where('tenant_id', $tenantId)
->find($fieldId);
if (! $field) {
throw new BadRequestHttpException(__('error.not_found'));
}
$field->delete();
}
public function reorder(int $categoryId, array $items): void
{
$tenantId = $this->tenantId();
$this->assertCategoryExists($tenantId, $categoryId);
$rows = $items['items'] ?? $items; // 둘 다 허용
if (! is_array($rows)) {
throw new BadRequestHttpException(__('error.invalid_payload'));
}
DB::transaction(function () use ($tenantId, $categoryId, $rows) {
foreach ($rows as $row) {
if (! isset($row['id'], $row['sort_order'])) {
continue;
}
CategoryField::query()
->where('tenant_id', $tenantId)
->where('category_id', $categoryId)
->where('id', $row['id'])
->update(['sort_order' => (int) $row['sort_order']]);
}
});
}
public function bulkUpsert(int $categoryId, array $items): array
{
$tenantId = $this->tenantId();
$userId = $this->apiUserId();
$this->assertCategoryExists($tenantId, $categoryId);
if (! is_array($items) || empty($items)) {
throw new BadRequestHttpException(__('error.empty_items'));
}
$result = ['created' => 0, 'updated' => 0];
DB::transaction(function () use ($tenantId, $userId, $categoryId, $items, &$result) {
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()
->where('tenant_id', $tenantId)
->where('category_id', $categoryId)
->find($payload['id']);
if (! $model) {
throw new BadRequestHttpException(__('error.not_found'));
}
// field_key 변경 유니크 검사
if (isset($payload['field_key']) && $payload['field_key'] !== $model->field_key) {
$dup = CategoryField::query()
->where('tenant_id', $tenantId)
->where('category_id', $categoryId)
->where('field_key', $payload['field_key'])
->exists();
if ($dup) {
throw new BadRequestHttpException(__('error.duplicate_key'));
}
}
$payload['updated_by'] = $userId;
$model->update($payload);
$result['updated']++;
} else {
// 신규 생성
if (empty($payload['field_key'])) {
throw new BadRequestHttpException(__('error.required', ['attr' => 'field_key']));
}
$dup = CategoryField::query()
->where('tenant_id', $tenantId)
->where('category_id', $categoryId)
->where('field_key', $payload['field_key'])
->exists();
if ($dup) {
throw new BadRequestHttpException(__('error.duplicate_key'));
}
$payload['tenant_id'] = $tenantId;
$payload['category_id'] = $categoryId;
$payload['is_required'] = $payload['is_required'] ?? false;
$payload['sort_order'] = $payload['sort_order'] ?? 0;
$payload['created_by'] = $userId;
CategoryField::create($payload);
$result['created']++;
}
}
});
return $result;
}
private function assertCategoryExists(int $tenantId, int $categoryId): void
{
$exists = Category::query()
->where('tenant_id', $tenantId)
->where('id', $categoryId)
->exists();
if (! $exists) {
throw new BadRequestHttpException(__('error.category_not_found'));
}
}
}