123 lines
3.9 KiB
PHP
123 lines
3.9 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Http\Controllers;
|
||
|
|
|
||
|
|
use App\Models\Category;
|
||
|
|
use App\Models\GlobalCategory;
|
||
|
|
use App\Models\Tenants\Tenant;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Illuminate\Http\Response;
|
||
|
|
use Illuminate\View\View;
|
||
|
|
|
||
|
|
class CategoryController extends Controller
|
||
|
|
{
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 관리 페이지
|
||
|
|
*/
|
||
|
|
public function index(Request $request): View|Response
|
||
|
|
{
|
||
|
|
// HTMX 요청 시 전체 페이지 리로드
|
||
|
|
if ($request->header('HX-Request')) {
|
||
|
|
return response('', 200)->header('HX-Redirect', route('categories.index'));
|
||
|
|
}
|
||
|
|
|
||
|
|
$tenantId = session('selected_tenant_id');
|
||
|
|
$tenant = $tenantId ? Tenant::find($tenantId) : null;
|
||
|
|
$isHQ = $tenantId == 1;
|
||
|
|
|
||
|
|
// 모든 code_group 조회 (글로벌 + 테넌트)
|
||
|
|
$globalGroups = GlobalCategory::whereNull('deleted_at')
|
||
|
|
->select('code_group')
|
||
|
|
->distinct()
|
||
|
|
->pluck('code_group')
|
||
|
|
->toArray();
|
||
|
|
|
||
|
|
$tenantGroups = [];
|
||
|
|
if ($tenantId) {
|
||
|
|
$tenantGroups = Category::where('tenant_id', $tenantId)
|
||
|
|
->whereNull('deleted_at')
|
||
|
|
->select('code_group')
|
||
|
|
->distinct()
|
||
|
|
->pluck('code_group')
|
||
|
|
->toArray();
|
||
|
|
}
|
||
|
|
|
||
|
|
$allGroups = array_unique(array_merge($globalGroups, $tenantGroups));
|
||
|
|
sort($allGroups);
|
||
|
|
|
||
|
|
$codeGroupLabels = config('categories.code_group_labels', []);
|
||
|
|
|
||
|
|
$codeGroups = [];
|
||
|
|
foreach ($allGroups as $group) {
|
||
|
|
$codeGroups[$group] = $codeGroupLabels[$group] ?? $group;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (empty($codeGroups)) {
|
||
|
|
$codeGroups['product'] = $codeGroupLabels['product'] ?? 'product';
|
||
|
|
}
|
||
|
|
|
||
|
|
$selectedGroup = $request->get('group', array_key_first($codeGroups));
|
||
|
|
if (! isset($codeGroups[$selectedGroup])) {
|
||
|
|
$selectedGroup = array_key_first($codeGroups);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 글로벌 카테고리 (트리 구조로 평탄화)
|
||
|
|
$globalCategoriesRaw = GlobalCategory::where('code_group', $selectedGroup)
|
||
|
|
->whereNull('deleted_at')
|
||
|
|
->orderBy('sort_order')
|
||
|
|
->get();
|
||
|
|
$globalCategories = $this->flattenTree($globalCategoriesRaw);
|
||
|
|
|
||
|
|
// 테넌트 카테고리 (트리 구조로 평탄화)
|
||
|
|
$tenantCategories = collect();
|
||
|
|
$tenantCodes = [];
|
||
|
|
if ($tenantId) {
|
||
|
|
$tenantCategoriesRaw = Category::where('tenant_id', $tenantId)
|
||
|
|
->where('code_group', $selectedGroup)
|
||
|
|
->whereNull('deleted_at')
|
||
|
|
->orderBy('sort_order')
|
||
|
|
->get();
|
||
|
|
$tenantCategories = $this->flattenTree($tenantCategoriesRaw);
|
||
|
|
$tenantCodes = $tenantCategoriesRaw->pluck('code')->toArray();
|
||
|
|
}
|
||
|
|
|
||
|
|
return view('categories.index', [
|
||
|
|
'codeGroups' => $codeGroups,
|
||
|
|
'codeGroupLabels' => $codeGroupLabels,
|
||
|
|
'selectedGroup' => $selectedGroup,
|
||
|
|
'globalCategories' => $globalCategories,
|
||
|
|
'tenantCategories' => $tenantCategories,
|
||
|
|
'tenantCodes' => $tenantCodes,
|
||
|
|
'tenant' => $tenant,
|
||
|
|
'isHQ' => $isHQ,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 컬렉션을 트리 구조로 평탄화 (부모-자식 순서 유지, depth 추가)
|
||
|
|
*/
|
||
|
|
private function flattenTree($categories): \Illuminate\Support\Collection
|
||
|
|
{
|
||
|
|
$result = collect();
|
||
|
|
$byParent = $categories->groupBy(fn($c) => $c->parent_id ?? 0);
|
||
|
|
|
||
|
|
$this->addChildrenRecursive($result, $byParent, 0, 0);
|
||
|
|
|
||
|
|
return $result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 재귀적으로 자식 추가
|
||
|
|
*/
|
||
|
|
private function addChildrenRecursive(&$result, $byParent, $parentId, $depth): void
|
||
|
|
{
|
||
|
|
$children = $byParent->get($parentId, collect());
|
||
|
|
|
||
|
|
foreach ($children as $child) {
|
||
|
|
$child->depth = $depth;
|
||
|
|
$result->push($child);
|
||
|
|
$this->addChildrenRecursive($result, $byParent, $child->id, $depth + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|