tenantId()) ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type'])) ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%")) ->orderBy('is_system', 'desc') ->orderBy('name') ->get(); } /** * 시스템 게시판 목록 (mng용) */ public function getSystemBoards(array $filters = []): Collection { return Board::systemOnly() ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type'])) ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%")) ->orderBy('name') ->get(); } /** * 시스템 게시판 페이징 목록 (mng용) */ public function getSystemBoardsPaginated(array $filters = [], int $perPage = 15): LengthAwarePaginator { return Board::systemOnly() ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type'])) ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%")) ->when(isset($filters['is_active']), fn ($q) => $q->where('is_active', $filters['is_active'])) ->orderBy('name') ->paginate($perPage); } /** * 테넌트 게시판만 가져오기 */ public function getTenantBoards(array $filters = []): Collection { return Board::tenantOnly($this->tenantId()) ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type'])) ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%")) ->orderBy('name') ->get(); } /** * 게시판 코드로 조회 (접근 가능한 게시판 중에서) */ public function getBoardByCode(string $code): ?Board { return Board::accessible($this->tenantId()) ->where('board_code', $code) ->first(); } /** * 시스템 게시판 코드로 조회 */ public function getSystemBoardByCode(string $code): ?Board { return Board::systemOnly() ->where('board_code', $code) ->where('is_active', true) ->first(); } /** * 테넌트 게시판 코드로 조회 */ public function getTenantBoardByCode(string $code): ?Board { return Board::tenantOnly($this->tenantId()) ->where('board_code', $code) ->where('is_active', true) ->first(); } /** * 시스템 게시판 ID로 조회 (mng용) */ public function getSystemBoardById(int $id): ?Board { return Board::systemOnly() ->with('customFields') ->find($id); } /** * 게시판 ID로 조회 (상세) */ public function getBoardDetail(int $id): ?Board { return Board::with('customFields') ->find($id); } // ========================================================================= // 생성 메서드 // ========================================================================= /** * 시스템 게시판 생성 (mng용) */ public function createSystemBoard(array $data): Board { $data['is_system'] = true; $data['tenant_id'] = null; $data['created_by'] = $this->apiUserId(); return Board::create($data); } /** * 테넌트 게시판 생성 (sam용) * - 게시판 생성 후 메뉴 자동 생성 */ public function createTenantBoard(array $data): Board { $data['is_system'] = false; $data['tenant_id'] = $this->tenantId(); $data['created_by'] = $this->apiUserId(); $board = Board::create($data); // 메뉴 자동 생성 MenuService::createMenuForBoard( $board->board_code, $board->name, $board->tenant_id ); return $board; } // ========================================================================= // 수정 메서드 // ========================================================================= /** * 시스템 게시판 수정 (mng용) */ public function updateSystemBoard(int $id, array $data): ?Board { $board = Board::systemOnly()->find($id); if (! $board) { return null; } $data['updated_by'] = $this->apiUserId(); $board->update($data); return $board->fresh(); } /** * 테넌트 게시판 수정 (sam용) * - 코드/이름 변경 시 메뉴도 자동 수정 */ public function updateTenantBoard(int $id, array $data): ?Board { $board = Board::tenantOnly($this->tenantId())->find($id); if (! $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(); } // ========================================================================= // 삭제 메서드 // ========================================================================= /** * 시스템 게시판 삭제 (mng용) */ public function deleteSystemBoard(int $id): bool { $board = Board::systemOnly()->find($id); if (! $board) { return false; } $board->deleted_by = $this->apiUserId(); $board->save(); $board->delete(); return true; } /** * 테넌트 게시판 삭제 (sam용) * - 게시판 삭제 시 메뉴도 자동 삭제 (Soft Delete) */ public function deleteTenantBoard(int $id): bool { $board = Board::tenantOnly($this->tenantId())->find($id); if (! $board) { 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; } // ========================================================================= // 필드 관리 메서드 // ========================================================================= /** * 게시판 필드 목록 조회 */ public function getBoardFields(int $boardId): Collection { return BoardSetting::where('board_id', $boardId) ->orderBy('sort_order') ->get(); } /** * 게시판 필드 추가 */ public function addBoardField(int $boardId, array $data): BoardSetting { $data['board_id'] = $boardId; $data['created_by'] = $this->apiUserId(); // 기본 정렬 순서 설정 if (! isset($data['sort_order'])) { $maxOrder = BoardSetting::where('board_id', $boardId)->max('sort_order') ?? 0; $data['sort_order'] = $maxOrder + 1; } return BoardSetting::create($data); } /** * 게시판 필드 수정 */ public function updateBoardField(int $fieldId, array $data): ?BoardSetting { $field = BoardSetting::find($fieldId); if (! $field) { return null; } $data['updated_by'] = $this->apiUserId(); $field->update($data); return $field->fresh(); } /** * 게시판 필드 삭제 */ public function deleteBoardField(int $fieldId): bool { $field = BoardSetting::find($fieldId); if (! $field) { return false; } return $field->delete(); } /** * 게시판 필드 순서 변경 */ public function reorderBoardFields(int $boardId, array $fieldIds): bool { foreach ($fieldIds as $order => $fieldId) { BoardSetting::where('id', $fieldId) ->where('board_id', $boardId) ->update(['sort_order' => $order + 1]); } return true; } // ========================================================================= // 유틸리티 메서드 // ========================================================================= /** * 게시판 코드 중복 확인 */ public function isCodeExists(string $code, ?int $excludeId = null): bool { $query = Board::where('board_code', $code); // 시스템 게시판이면 시스템 게시판 중에서 확인 // 테넌트 게시판이면 해당 테넌트 중에서 확인 $query->where(function ($q) { $q->where('is_system', true) ->orWhere('tenant_id', $this->tenantIdOrNull()); }); if ($excludeId) { $query->where('id', '!=', $excludeId); } return $query->exists(); } /** * 게시판 활성/비활성 토글 */ public function toggleActive(int $id): ?Board { $board = Board::find($id); if (! $board) { return null; } $board->is_active = ! $board->is_active; $board->updated_by = $this->apiUserId(); $board->save(); return $board; } }