feat:동기화 페이지에 글로벌/테넌트 필터 추가

- 환경 탭 앞에 글로벌/테넌트 토글 버튼 추가
- 글로벌: tenant_id가 NULL인 코드/카테고리만 표시
- 테넌트: 현재 선택된 테넌트의 데이터만 표시
- Push/Pull API에 type 파라미터 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-29 01:06:33 +09:00
parent 50f9fa2fd3
commit 1e70d2edbf
4 changed files with 198 additions and 119 deletions

View File

@@ -50,9 +50,10 @@ public function index(Request $request): View|Response
$environments = $this->getEnvironments();
$selectedEnv = $request->get('env', 'dev');
$selectedType = $request->get('type', 'global'); // global or tenant
// 로컬 카테고리 조회
$localCategories = $this->getCategoryList();
// 로컬 카테고리 조회 (타입 필터 적용)
$localCategories = $this->getCategoryList($selectedType);
// 원격 카테고리 조회
$remoteCategories = [];
@@ -60,7 +61,7 @@ public function index(Request $request): View|Response
if (! empty($environments[$selectedEnv]['url'])) {
try {
$remoteCategories = $this->fetchRemoteCategories($environments[$selectedEnv]);
$remoteCategories = $this->fetchRemoteCategories($environments[$selectedEnv], $selectedType);
} catch (\Exception $e) {
$remoteError = $e->getMessage();
}
@@ -72,6 +73,7 @@ public function index(Request $request): View|Response
return view('categories.sync', [
'environments' => $environments,
'selectedEnv' => $selectedEnv,
'selectedType' => $selectedType,
'localCategories' => $localCategories,
'remoteCategories' => $remoteCategories,
'remoteError' => $remoteError,
@@ -92,7 +94,8 @@ public function export(Request $request): JsonResponse
return response()->json(['error' => 'Unauthorized'], 401);
}
$categories = $this->getCategoryList();
$type = $request->get('type', 'all'); // global, tenant, or all
$categories = $this->getCategoryList($type);
return response()->json([
'success' => true,
@@ -216,6 +219,7 @@ public function push(Request $request): JsonResponse
{
$validated = $request->validate([
'env' => 'required|string|in:dev,prod',
'type' => 'required|string|in:global,tenant',
'category_keys' => 'required|array|min:1',
'category_keys.*' => 'string',
]);
@@ -227,8 +231,8 @@ public function push(Request $request): JsonResponse
return response()->json(['error' => '환경 설정이 없습니다.'], 400);
}
// 선택된 카테고리 조회
$localCategories = $this->getCategoryList();
// 선택된 카테고리 조회 (타입 필터 적용)
$localCategories = $this->getCategoryList($validated['type']);
$selectedCategories = array_filter($localCategories, function ($cat) use ($validated) {
$key = $this->makeCategoryKey($cat);
return in_array($key, $validated['category_keys']);
@@ -271,6 +275,7 @@ public function pull(Request $request): JsonResponse
{
$validated = $request->validate([
'env' => 'required|string|in:dev,prod',
'type' => 'required|string|in:global,tenant',
'category_keys' => 'required|array|min:1',
'category_keys.*' => 'string',
]);
@@ -282,9 +287,9 @@ public function pull(Request $request): JsonResponse
return response()->json(['error' => '환경 설정이 없습니다.'], 400);
}
// 원격 카테고리 조회
// 원격 카테고리 조회 (타입 필터 적용)
try {
$remoteCategories = $this->fetchRemoteCategories($env);
$remoteCategories = $this->fetchRemoteCategories($env, $validated['type']);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
@@ -378,65 +383,70 @@ public function pull(Request $request): JsonResponse
}
/**
* 카테고리 목록 조회 (글로벌 + 테넌트)
* 카테고리 목록 조회
* @param string $type 'global', 'tenant', or 'all'
*/
private function getCategoryList(): array
private function getCategoryList(string $type = 'all'): array
{
$tenantId = $this->getTenantId();
$categories = [];
// 글로벌 카테고리
$globalCategories = GlobalCategory::whereNull('deleted_at')
->orderBy('code_group')
->orderBy('sort_order')
->get();
if ($type === 'global' || $type === 'all') {
$globalCategories = GlobalCategory::whereNull('deleted_at')
->orderBy('code_group')
->orderBy('sort_order')
->get();
foreach ($globalCategories as $cat) {
$parentCode = null;
if ($cat->parent_id) {
$parent = GlobalCategory::find($cat->parent_id);
$parentCode = $parent?->code;
foreach ($globalCategories as $cat) {
$parentCode = null;
if ($cat->parent_id) {
$parent = GlobalCategory::find($cat->parent_id);
$parentCode = $parent?->code;
}
$categories[] = [
'is_global' => true,
'tenant_id' => null,
'code_group' => $cat->code_group,
'code' => $cat->code,
'name' => $cat->name,
'parent_code' => $parentCode,
'sort_order' => $cat->sort_order,
'description' => $cat->description,
'is_active' => $cat->is_active,
];
}
$categories[] = [
'is_global' => true,
'tenant_id' => null,
'code_group' => $cat->code_group,
'code' => $cat->code,
'name' => $cat->name,
'parent_code' => $parentCode,
'sort_order' => $cat->sort_order,
'description' => $cat->description,
'is_active' => $cat->is_active,
];
}
// 테넌트 카테고리
$tenantCategories = Category::withoutGlobalScopes()
->where('tenant_id', $tenantId)
->whereNull('deleted_at')
->orderBy('code_group')
->orderBy('sort_order')
->get();
if ($type === 'tenant' || $type === 'all') {
$tenantCategories = Category::withoutGlobalScopes()
->where('tenant_id', $tenantId)
->whereNull('deleted_at')
->orderBy('code_group')
->orderBy('sort_order')
->get();
foreach ($tenantCategories as $cat) {
$parentCode = null;
if ($cat->parent_id) {
$parent = Category::withoutGlobalScopes()->find($cat->parent_id);
$parentCode = $parent?->code;
foreach ($tenantCategories as $cat) {
$parentCode = null;
if ($cat->parent_id) {
$parent = Category::withoutGlobalScopes()->find($cat->parent_id);
$parentCode = $parent?->code;
}
$categories[] = [
'is_global' => false,
'tenant_id' => $cat->tenant_id,
'code_group' => $cat->code_group,
'code' => $cat->code,
'name' => $cat->name,
'parent_code' => $parentCode,
'sort_order' => $cat->sort_order,
'description' => $cat->description,
'is_active' => $cat->is_active,
];
}
$categories[] = [
'is_global' => false,
'tenant_id' => $cat->tenant_id,
'code_group' => $cat->code_group,
'code' => $cat->code,
'name' => $cat->name,
'parent_code' => $parentCode,
'sort_order' => $cat->sort_order,
'description' => $cat->description,
'is_active' => $cat->is_active,
];
}
return $categories;
@@ -445,12 +455,14 @@ private function getCategoryList(): array
/**
* 원격 카테고리 조회
*/
private function fetchRemoteCategories(array $env): array
private function fetchRemoteCategories(array $env, string $type = 'all'): array
{
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $env['api_key'],
'Accept' => 'application/json',
])->timeout(10)->get(rtrim($env['url'], '/') . '/category-sync/export');
])->timeout(10)->get(rtrim($env['url'], '/') . '/category-sync/export', [
'type' => $type,
]);
if (! $response->successful()) {
throw new \Exception('API 오류: HTTP ' . $response->status());