Files
sam-api/app/Services/TenantOptionValueService.php
hskwon cc206fdbed style: Laravel Pint 코드 포맷팅 적용
- PSR-12 스타일 가이드 준수
- 302개 파일 스타일 이슈 자동 수정
- 코드 로직 변경 없음 (포맷팅만)
2025-11-06 17:45:49 +09:00

230 lines
7.0 KiB
PHP

<?php
namespace App\Services;
use App\Models\Tenants\TenantOptionGroup;
use App\Models\Tenants\TenantOptionValue;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
class TenantOptionValueService
{
/** 활성 테넌트 ID */
protected static function tenantId(): ?int
{
return app('tenant_id');
}
/** 테넌트 소유 그룹 로드 (없으면 null) */
protected static function loadGroup(int $tenantId, int $groupId): ?TenantOptionGroup
{
return TenantOptionGroup::where('tenant_id', $tenantId)->find($groupId);
}
/**
* [GET] 옵션 값 목록
* params: active_only?(bool)
*/
public static function index(int $groupId, array $params = [])
{
$tenantId = self::tenantId();
if (! $tenantId) {
return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
}
$group = self::loadGroup($tenantId, $groupId);
if (! $group) {
return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
}
$q = TenantOptionValue::where('group_id', $group->id)
->orderBy('sort_order')
->orderBy('value_label');
if (! empty($params['active_only'])) {
$q->where('is_active', 1);
}
$list = $q->get();
return $list;
}
/**
* [POST] 옵션 값 생성
*/
public static function store(int $groupId, array $params = [])
{
$tenantId = self::tenantId();
if (! $tenantId) {
return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
}
$group = self::loadGroup($tenantId, $groupId);
if (! $group) {
return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
}
$v = Validator::make($params, [
'value_key' => [
'required', 'string', 'max:64', 'alpha_dash',
Rule::unique('tenant_option_values', 'value_key')
->where(fn ($q) => $q->where('group_id', $group->id)),
],
'value_label' => ['required', 'string', 'max:100'],
'sort_order' => ['nullable', 'integer'],
'is_active' => ['nullable', 'boolean'],
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
$data = $v->validated();
$data['group_id'] = $group->id;
$item = TenantOptionValue::create($data);
return $item->toArray();
}
/**
* [GET] 옵션 값 단건 조회
*/
public static function show(int $groupId, int $id)
{
$tenantId = self::tenantId();
if (! $tenantId) {
return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
}
$group = self::loadGroup($tenantId, $groupId);
if (! $group) {
return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
}
$item = TenantOptionValue::where('group_id', $group->id)->find($id);
if (! $item) {
return ['error' => '옵션 값을 찾을 수 없습니다.', 'code' => 404];
}
return $item->toArray();
}
/**
* [PATCH] 옵션 값 수정
*/
public static function update(int $groupId, int $id, array $params = [])
{
$tenantId = self::tenantId();
if (! $tenantId) {
return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
}
$group = self::loadGroup($tenantId, $groupId);
if (! $group) {
return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
}
$item = TenantOptionValue::where('group_id', $group->id)->find($id);
if (! $item) {
return ['error' => '옵션 값을 찾을 수 없습니다.', 'code' => 404];
}
$v = Validator::make($params, [
'value_key' => [
'sometimes', 'string', 'max:64', 'alpha_dash',
Rule::unique('tenant_option_values', 'value_key')
->where(fn ($q) => $q->where('group_id', $group->id))
->ignore($item->id),
],
'value_label' => ['sometimes', 'string', 'max:100'],
'sort_order' => ['nullable', 'integer'],
'is_active' => ['nullable', 'boolean'],
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
$data = $v->validated();
if (empty($data)) {
return ['error' => '수정할 항목이 없습니다.', 'code' => 422];
}
$item->fill($data)->save();
return $item->toArray();
}
/**
* [DELETE] 옵션 값 삭제
* - TODO: 실제 프로필/필드설정에서 value_key 참조 여부 체크가 필요하면 여기서 차단
*/
public static function destroy(int $groupId, int $id)
{
$tenantId = self::tenantId();
if (! $tenantId) {
return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
}
$group = self::loadGroup($tenantId, $groupId);
if (! $group) {
return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
}
$item = TenantOptionValue::where('group_id', $group->id)->find($id);
if (! $item) {
return ['error' => '옵션 값을 찾을 수 없습니다.', 'code' => 404];
}
// TODO: 참조 무결성 검사(필요 시 구현)
$item->delete();
return ['deleted' => true];
}
/**
* [PATCH] 정렬 순서 일괄 변경
* params: items: [{id, sort_order}, ...]
*/
public static function reorder(int $groupId, array $params = [])
{
$tenantId = self::tenantId();
if (! $tenantId) {
return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
}
$group = self::loadGroup($tenantId, $groupId);
if (! $group) {
return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
}
$v = Validator::make($params, [
'items' => ['required', 'array', 'min:1'],
'items.*.id' => ['required', 'integer'],
'items.*.sort_order' => ['required', 'integer'],
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
$rows = $v->validated()['items'];
try {
DB::transaction(function () use ($group, $rows) {
foreach ($rows as $r) {
TenantOptionValue::where('group_id', $group->id)
->where('id', $r['id'])
->update(['sort_order' => (int) $r['sort_order']]);
}
});
} catch (\Throwable $e) {
return ['error' => '정렬 순서 저장 중 오류가 발생했습니다.', 'code' => 500];
}
return ['reordered' => true];
}
}