fix : 테넌트별 옵션설정 작업
- Tenant Fields - Tenant Option Groups - Tenant Option Values - Tenant Profiles
This commit is contained in:
231
app/Services/TenantOptionValueService.php
Normal file
231
app/Services/TenantOptionValueService.php
Normal file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Helpers\ApiResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Models\Tenants\TenantOptionGroup;
|
||||
use App\Models\Tenants\TenantOptionValue;
|
||||
|
||||
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 ApiResponse::error('활성 테넌트가 없습니다.', 400);
|
||||
}
|
||||
|
||||
$group = self::loadGroup($tenantId, $groupId);
|
||||
if (!$group) {
|
||||
return ApiResponse::error('옵션 그룹을 찾을 수 없습니다.', 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 ApiResponse::response('result', $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* [POST] 옵션 값 생성
|
||||
*/
|
||||
public static function store(int $groupId, array $params = [])
|
||||
{
|
||||
$tenantId = self::tenantId();
|
||||
if (!$tenantId) {
|
||||
return ApiResponse::error('활성 테넌트가 없습니다.', 400);
|
||||
}
|
||||
|
||||
$group = self::loadGroup($tenantId, $groupId);
|
||||
if (!$group) {
|
||||
return ApiResponse::error('옵션 그룹을 찾을 수 없습니다.', 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 ApiResponse::error($v->errors()->first(), 422);
|
||||
}
|
||||
|
||||
$data = $v->validated();
|
||||
$data['group_id'] = $group->id;
|
||||
$item = TenantOptionValue::create($data);
|
||||
|
||||
return ApiResponse::response('result', $item->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* [GET] 옵션 값 단건 조회
|
||||
*/
|
||||
public static function show(int $groupId, int $id)
|
||||
{
|
||||
$tenantId = self::tenantId();
|
||||
if (!$tenantId) {
|
||||
return ApiResponse::error('활성 테넌트가 없습니다.', 400);
|
||||
}
|
||||
|
||||
$group = self::loadGroup($tenantId, $groupId);
|
||||
if (!$group) {
|
||||
return ApiResponse::error('옵션 그룹을 찾을 수 없습니다.', 404);
|
||||
}
|
||||
|
||||
$item = TenantOptionValue::where('group_id', $group->id)->find($id);
|
||||
if (!$item) {
|
||||
return ApiResponse::error('옵션 값을 찾을 수 없습니다.', 404);
|
||||
}
|
||||
|
||||
return ApiResponse::response('result', $item->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* [PATCH] 옵션 값 수정
|
||||
*/
|
||||
public static function update(int $groupId, int $id, array $params = [])
|
||||
{
|
||||
$tenantId = self::tenantId();
|
||||
if (!$tenantId) {
|
||||
return ApiResponse::error('활성 테넌트가 없습니다.', 400);
|
||||
}
|
||||
|
||||
$group = self::loadGroup($tenantId, $groupId);
|
||||
if (!$group) {
|
||||
return ApiResponse::error('옵션 그룹을 찾을 수 없습니다.', 404);
|
||||
}
|
||||
|
||||
$item = TenantOptionValue::where('group_id', $group->id)->find($id);
|
||||
if (!$item) {
|
||||
return ApiResponse::error('옵션 값을 찾을 수 없습니다.', 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 ApiResponse::error($v->errors()->first(), 422);
|
||||
}
|
||||
|
||||
$data = $v->validated();
|
||||
if (empty($data)) {
|
||||
return ApiResponse::error('수정할 항목이 없습니다.', 422);
|
||||
}
|
||||
|
||||
$item->fill($data)->save();
|
||||
|
||||
return ApiResponse::response('result', $item->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* [DELETE] 옵션 값 삭제
|
||||
* - TODO: 실제 프로필/필드설정에서 value_key 참조 여부 체크가 필요하면 여기서 차단
|
||||
*/
|
||||
public static function destroy(int $groupId, int $id)
|
||||
{
|
||||
$tenantId = self::tenantId();
|
||||
if (!$tenantId) {
|
||||
return ApiResponse::error('활성 테넌트가 없습니다.', 400);
|
||||
}
|
||||
|
||||
$group = self::loadGroup($tenantId, $groupId);
|
||||
if (!$group) {
|
||||
return ApiResponse::error('옵션 그룹을 찾을 수 없습니다.', 404);
|
||||
}
|
||||
|
||||
$item = TenantOptionValue::where('group_id', $group->id)->find($id);
|
||||
if (!$item) {
|
||||
return ApiResponse::error('옵션 값을 찾을 수 없습니다.', 404);
|
||||
}
|
||||
|
||||
// TODO: 참조 무결성 검사(필요 시 구현)
|
||||
$item->delete();
|
||||
|
||||
return ApiResponse::response('result', ['deleted' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* [PATCH] 정렬 순서 일괄 변경
|
||||
* params: items: [{id, sort_order}, ...]
|
||||
*/
|
||||
public static function reorder(int $groupId, array $params = [])
|
||||
{
|
||||
$tenantId = self::tenantId();
|
||||
if (!$tenantId) {
|
||||
return ApiResponse::error('활성 테넌트가 없습니다.', 400);
|
||||
}
|
||||
|
||||
$group = self::loadGroup($tenantId, $groupId);
|
||||
if (!$group) {
|
||||
return ApiResponse::error('옵션 그룹을 찾을 수 없습니다.', 404);
|
||||
}
|
||||
|
||||
$v = Validator::make($params, [
|
||||
'items' => ['required','array','min:1'],
|
||||
'items.*.id' => ['required','integer'],
|
||||
'items.*.sort_order' => ['required','integer'],
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return ApiResponse::error($v->errors()->first(), 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 ApiResponse::error('정렬 순서 저장 중 오류가 발생했습니다.', 500);
|
||||
}
|
||||
|
||||
return ApiResponse::response('result', ['reordered' => true]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user