diff --git a/app/Services/Boards/BoardService.php b/app/Services/Boards/BoardService.php index 273e604..9118e75 100644 --- a/app/Services/Boards/BoardService.php +++ b/app/Services/Boards/BoardService.php @@ -4,6 +4,7 @@ use App\Models\Boards\Board; use App\Models\Boards\BoardSetting; +use App\Services\MenuService; use App\Services\Service; use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Database\Eloquent\Collection; @@ -133,6 +134,7 @@ public function createSystemBoard(array $data): Board /** * 테넌트 게시판 생성 (sam용) + * - 게시판 생성 후 메뉴 자동 생성 */ public function createTenantBoard(array $data): Board { @@ -140,7 +142,16 @@ public function createTenantBoard(array $data): Board $data['tenant_id'] = $this->tenantId(); $data['created_by'] = $this->apiUserId(); - return Board::create($data); + $board = Board::create($data); + + // 메뉴 자동 생성 + MenuService::createMenuForBoard( + $board->board_code, + $board->name, + $board->tenant_id + ); + + return $board; } // ========================================================================= @@ -166,6 +177,7 @@ public function updateSystemBoard(int $id, array $data): ?Board /** * 테넌트 게시판 수정 (sam용) + * - 코드/이름 변경 시 메뉴도 자동 수정 */ public function updateTenantBoard(int $id, array $data): ?Board { @@ -175,9 +187,26 @@ public function updateTenantBoard(int $id, array $data): ?Board return null; } + // 기존 코드/이름 저장 (메뉴 업데이트용) + $oldCode = $board->board_code; + $oldName = $board->name; + $data['updated_by'] = $this->apiUserId(); $board->update($data); + // 코드 또는 이름 변경 시 메뉴도 업데이트 + $newCode = $data['board_code'] ?? $oldCode; + $newName = $data['name'] ?? $oldName; + + if ($oldCode !== $newCode || $oldName !== $newName) { + MenuService::updateMenuForBoard( + $oldCode, + $newCode, + $newName, + $board->tenant_id + ); + } + return $board->fresh(); } @@ -205,6 +234,7 @@ public function deleteSystemBoard(int $id): bool /** * 테넌트 게시판 삭제 (sam용) + * - 게시판 삭제 시 메뉴도 자동 삭제 (Soft Delete) */ public function deleteTenantBoard(int $id): bool { @@ -214,10 +244,16 @@ public function deleteTenantBoard(int $id): bool return false; } + $boardCode = $board->board_code; + $tenantId = $board->tenant_id; + $board->deleted_by = $this->apiUserId(); $board->save(); $board->delete(); + // 메뉴도 함께 삭제 (Soft Delete) + MenuService::deleteMenuForBoard($boardCode, $tenantId); + return true; } diff --git a/app/Services/MenuService.php b/app/Services/MenuService.php index b20a2f0..f0bb962 100644 --- a/app/Services/MenuService.php +++ b/app/Services/MenuService.php @@ -426,4 +426,171 @@ public static function trashedList(array $params = []) ->orderBy('deleted_at', 'desc') ->get(); } + + // ========================================================================= + // 게시판 메뉴 연동 메서드 (테넌트 게시판 전용) + // ========================================================================= + + /** + * 테넌트 게시판용 메뉴 생성 + * + * @param string $boardCode 게시판 코드 + * @param string $boardName 게시판 이름 + * @param int $tenantId 테넌트 ID + * @return Menu|null 생성된 메뉴 또는 null (중복 시) + */ + public static function createMenuForBoard(string $boardCode, string $boardName, int $tenantId): ?Menu + { + $url = '/boards/'.$boardCode; + $userId = self::actorId(); + + // 중복 체크 + if (Menu::where('url', $url)->where('tenant_id', $tenantId)->exists()) { + return null; + } + + // 부모 메뉴 찾기 + $parentId = self::findParentMenuForBoard($tenantId); + + // 정렬 순서 계산 + $maxOrder = Menu::where('tenant_id', $tenantId) + ->where('parent_id', $parentId) + ->max('sort_order') ?? 0; + + return Menu::create([ + 'tenant_id' => $tenantId, + 'parent_id' => $parentId, + 'name' => $boardName, + 'url' => $url, + 'icon' => 'document-text', + 'sort_order' => $maxOrder + 1, + 'is_active' => true, + 'hidden' => false, + 'is_external' => false, + 'created_by' => $userId, + 'updated_by' => $userId, + ]); + } + + /** + * 테넌트 게시판 메뉴의 부모 메뉴 ID 찾기 + * 우선순위: /board → /boards → /customer-center → null (최상위) + * + * @param int $tenantId 테넌트 ID + * @return int|null 부모 메뉴 ID + */ + protected static function findParentMenuForBoard(int $tenantId): ?int + { + $priorityUrls = ['/board', '/boards', '/customer-center']; + + foreach ($priorityUrls as $url) { + $menu = Menu::where('tenant_id', $tenantId) + ->where('url', $url) + ->first(); + + if ($menu) { + return $menu->id; + } + } + + return null; + } + + /** + * 테넌트 게시판용 메뉴 수정 (코드/이름 변경 시) + * + * @param string $oldCode 기존 게시판 코드 + * @param string $newCode 새 게시판 코드 + * @param string $newName 새 게시판 이름 + * @param int $tenantId 테넌트 ID + * @return bool 수정 성공 여부 + */ + public static function updateMenuForBoard(string $oldCode, string $newCode, string $newName, int $tenantId): bool + { + $oldUrl = '/boards/'.$oldCode; + $newUrl = '/boards/'.$newCode; + + $menu = Menu::where('url', $oldUrl) + ->where('tenant_id', $tenantId) + ->first(); + + if (! $menu) { + return false; + } + + $menu->url = $newUrl; + $menu->name = $newName; + $menu->updated_by = self::actorId(); + $menu->save(); + + return true; + } + + /** + * 테넌트 게시판용 메뉴 삭제 (Soft Delete) + * + * @param string $boardCode 게시판 코드 + * @param int $tenantId 테넌트 ID + * @param bool $forceDelete 영구 삭제 여부 + * @return bool 삭제 성공 여부 + */ + public static function deleteMenuForBoard(string $boardCode, int $tenantId, bool $forceDelete = false): bool + { + $url = '/boards/'.$boardCode; + + $query = $forceDelete + ? Menu::withTrashed()->where('url', $url)->where('tenant_id', $tenantId) + : Menu::where('url', $url)->where('tenant_id', $tenantId); + + $menu = $query->first(); + + if (! $menu) { + return false; + } + + if (! $forceDelete) { + $menu->deleted_by = self::actorId(); + $menu->save(); + } + + return $forceDelete ? $menu->forceDelete() : $menu->delete(); + } + + /** + * 테넌트 게시판용 메뉴 복원 + * + * @param string $boardCode 게시판 코드 + * @param string $boardName 게시판 이름 + * @param int $tenantId 테넌트 ID + * @return bool 복원 성공 여부 + */ + public static function restoreMenuForBoard(string $boardCode, string $boardName, int $tenantId): bool + { + $url = '/boards/'.$boardCode; + + // 1. soft-deleted 메뉴 확인 + $trashedMenu = Menu::onlyTrashed() + ->where('url', $url) + ->where('tenant_id', $tenantId) + ->first(); + + if ($trashedMenu) { + $trashedMenu->restore(); + $trashedMenu->deleted_by = null; + $trashedMenu->updated_by = self::actorId(); + $trashedMenu->save(); + + return true; + } + + // 2. 이미 활성 메뉴가 있는지 확인 + if (Menu::where('url', $url)->where('tenant_id', $tenantId)->exists()) { + return true; // 이미 존재하면 성공으로 처리 + } + + // 3. 둘 다 없으면 새로 생성 + $newMenu = self::createMenuForBoard($boardCode, $boardName, $tenantId); + + return $newMenu !== null; + } }