247 lines
9.0 KiB
PHP
247 lines
9.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|
use App\Models\Commons\CategoryField; // 가정: Eloquent 모델 경로
|
|
use App\Models\Commons\Category;
|
|
|
|
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);
|
|
|
|
$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();
|
|
|
|
// 카테고리 내 field_key 유니크 검증
|
|
$exists = CategoryField::query()
|
|
->where(compact('tenant_id'))
|
|
->where('category_id', $categoryId)
|
|
->where('field_key', $payload['field_key'])
|
|
->exists();
|
|
if ($exists) {
|
|
throw new BadRequestHttpException(__('error.duplicate_key')); // ko/error.php에 매핑
|
|
}
|
|
|
|
$payload['tenant_id'] = $tenantId;
|
|
$payload['category_id'] = $categoryId;
|
|
$payload['is_required'] = $payload['is_required'] ?? 'N';
|
|
$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'));
|
|
}
|
|
|
|
$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();
|
|
|
|
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 $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();
|
|
|
|
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'] ?? 'N';
|
|
$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'));
|
|
}
|
|
}
|
|
}
|