diff --git a/app/Services/Boards/PostService.php b/app/Services/Boards/PostService.php index 9abaf7c..3e61dd9 100644 --- a/app/Services/Boards/PostService.php +++ b/app/Services/Boards/PostService.php @@ -12,6 +12,24 @@ class PostService extends Service { + /** + * 본사 테넌트 ID (시스템 게시판에서 본사 글은 모든 테넌트에게 공개) + */ + private const HQ_TENANT_ID = 1; + + /** + * 시스템 게시판 조회 조건 적용 + * - 본사(HQ_TENANT_ID) 글은 모든 테넌트에게 공개 + * - 각 테넌트 글은 해당 테넌트만 조회 가능 + */ + private function applySystemBoardScope($query): void + { + $query->where(function ($q) { + $q->where('tenant_id', self::HQ_TENANT_ID) + ->orWhere('tenant_id', $this->tenantId()); + }); + } + // ========================================================================= // 게시글 조회 메서드 // ========================================================================= @@ -19,14 +37,20 @@ class PostService extends Service /** * 게시글 목록 조회 (페이징) * - * @param bool $isSystemBoard 시스템 게시판 여부 (시스템 게시판은 tenant_id 필터 제외) + * @param bool $isSystemBoard 시스템 게시판 여부 + * - 시스템 게시판: 본사(tenant_id=1) 글 + 현재 테넌트 글 조회 + * - 일반 게시판: 현재 테넌트 글만 조회 */ public function getPostsByBoard(int $boardId, array $filters = [], int $perPage = 15, bool $isSystemBoard = false): LengthAwarePaginator { return Post::where('board_id', $boardId) - // 시스템 게시판: tenant_id 필터 없음 (모든 게시글 조회) - // 일반 게시판: 현재 테넌트 게시글만 조회 - ->when(! $isSystemBoard, fn ($q) => $q->where('tenant_id', $this->tenantId())) + ->when($isSystemBoard, function ($q) { + // 시스템 게시판: 본사(HQ) 글 + 현재 테넌트 글 + $q->where(function ($query) { + $query->where('tenant_id', self::HQ_TENANT_ID) + ->orWhere('tenant_id', $this->tenantId()); + }); + }, fn ($q) => $q->where('tenant_id', $this->tenantId())) ->when(isset($filters['search']), function ($q) use ($filters) { $q->where(function ($query) use ($filters) { $query->where('title', 'like', "%{$filters['search']}%") @@ -89,13 +113,18 @@ public function getPost(int $postId, ?bool $isSystemBoard = null): ?Post if ($isSystemBoard === null) { // 게시글에서 board 정보로 시스템 게시판 여부 판단 - // 시스템 게시판이면 tenant_id 필터 없음 $query->where(function ($q) { + // 현재 테넌트 글 $q->where('tenant_id', $this->tenantId()) - ->orWhereHas('board', fn ($b) => $b->where('is_system', true)); + // 또는 시스템 게시판의 본사 글 + ->orWhere(function ($sub) { + $sub->where('tenant_id', self::HQ_TENANT_ID) + ->whereHas('board', fn ($b) => $b->where('is_system', true)); + }); }); } elseif ($isSystemBoard) { - // 시스템 게시판: tenant_id 필터 없음 + // 시스템 게시판: 본사 글 + 현재 테넌트 글 + $this->applySystemBoardScope($query); } else { $query->where('tenant_id', $this->tenantId()); } @@ -133,9 +162,11 @@ public function getPostByCodeAndId(string $boardCode, int $postId): ?Post $query = Post::with(['files', 'comments.replies', 'board']) ->where('board_id', $board->id); - // 시스템 게시판: tenant_id 필터 없음 + // 시스템 게시판: 본사 글 + 현재 테넌트 글 // 일반 게시판: 현재 테넌트 게시글만 조회 - if (! $board->is_system) { + if ($board->is_system) { + $this->applySystemBoardScope($query); + } else { $query->where('tenant_id', $this->tenantId()); } @@ -156,9 +187,13 @@ public function getPostBySystemBoardCodeAndId(string $boardCode, int $postId): ? return null; } - return Post::with(['files', 'comments.replies', 'board']) - ->where('board_id', $board->id) - ->find($postId); + $query = Post::with(['files', 'comments.replies', 'board']) + ->where('board_id', $board->id); + + // 시스템 게시판: 본사 글 + 현재 테넌트 글 + $this->applySystemBoardScope($query); + + return $query->find($postId); } /** @@ -193,7 +228,7 @@ public function getPostByTenantBoardCodeAndId(string $boardCode, int $postId): ? public function createPost(int $boardId, array $data, bool $isSystemBoard = false): Post { $data['board_id'] = $boardId; - $data['tenant_id'] = $isSystemBoard ? null : $this->tenantId(); + $data['tenant_id'] = $this->tenantId(); // 시스템 게시판도 tenant_id 설정 (본사=1의 글만 전체 공개) $data['user_id'] = $this->apiUserId(); $data['ip_address'] = request()->ip(); $data['status'] = $data['status'] ?? 'published'; @@ -203,7 +238,7 @@ public function createPost(int $boardId, array $data, bool $isSystemBoard = fals // 커스텀 필드 저장 if (isset($data['custom_fields'])) { - $this->saveCustomFields($post->id, $data['custom_fields']); + $this->saveCustomFields($post->id, $boardId, $data['custom_fields']); } return $post->fresh(['board', 'files']); @@ -262,13 +297,18 @@ public function updatePost(int $postId, array $data, ?bool $isSystemBoard = null if ($isSystemBoard === null) { // 게시글에서 board 정보로 시스템 게시판 여부 판단 - // 시스템 게시판이면 tenant_id 필터 없음 $query->where(function ($q) { + // 현재 테넌트 글 $q->where('tenant_id', $this->tenantId()) - ->orWhereHas('board', fn ($b) => $b->where('is_system', true)); + // 또는 시스템 게시판의 본사 글 + ->orWhere(function ($sub) { + $sub->where('tenant_id', self::HQ_TENANT_ID) + ->whereHas('board', fn ($b) => $b->where('is_system', true)); + }); }); } elseif ($isSystemBoard) { - // 시스템 게시판: tenant_id 필터 없음 + // 시스템 게시판: 본사 글 + 현재 테넌트 글 + $this->applySystemBoardScope($query); } else { $query->where('tenant_id', $this->tenantId()); } @@ -283,7 +323,7 @@ public function updatePost(int $postId, array $data, ?bool $isSystemBoard = null // 커스텀 필드 업데이트 if (isset($data['custom_fields'])) { - $this->saveCustomFields($post->id, $data['custom_fields']); + $this->saveCustomFields($post->id, $post->board_id, $data['custom_fields']); } return $post->fresh(['board', 'files']); @@ -304,9 +344,11 @@ public function updatePostByBoardCode(string $boardCode, int $postId, array $dat $query = Post::where('board_id', $board->id); - // 시스템 게시판: tenant_id 필터 없음 + // 시스템 게시판: 본사 글 + 현재 테넌트 글 // 일반 게시판: 현재 테넌트 게시글만 - if (! $board->is_system) { + if ($board->is_system) { + $this->applySystemBoardScope($query); + } else { $query->where('tenant_id', $this->tenantId()); } @@ -319,7 +361,7 @@ public function updatePostByBoardCode(string $boardCode, int $postId, array $dat $post->update($data); if (isset($data['custom_fields'])) { - $this->saveCustomFields($post->id, $data['custom_fields']); + $this->saveCustomFields($post->id, $board->id, $data['custom_fields']); } return $post->fresh(['board', 'files']); @@ -339,7 +381,12 @@ public function updatePostBySystemBoardCode(string $boardCode, int $postId, arra return null; } - $post = Post::where('board_id', $board->id)->find($postId); + $query = Post::where('board_id', $board->id); + + // 시스템 게시판: 본사 글 + 현재 테넌트 글 + $this->applySystemBoardScope($query); + + $post = $query->find($postId); if (! $post) { return null; @@ -348,7 +395,7 @@ public function updatePostBySystemBoardCode(string $boardCode, int $postId, arra $post->update($data); if (isset($data['custom_fields'])) { - $this->saveCustomFields($post->id, $data['custom_fields']); + $this->saveCustomFields($post->id, $board->id, $data['custom_fields']); } return $post->fresh(['board', 'files']); @@ -379,7 +426,7 @@ public function updatePostByTenantBoardCode(string $boardCode, int $postId, arra $post->update($data); if (isset($data['custom_fields'])) { - $this->saveCustomFields($post->id, $data['custom_fields']); + $this->saveCustomFields($post->id, $board->id, $data['custom_fields']); } return $post->fresh(['board', 'files']); @@ -400,13 +447,18 @@ public function deletePost(int $postId, ?bool $isSystemBoard = null): bool if ($isSystemBoard === null) { // 게시글에서 board 정보로 시스템 게시판 여부 판단 - // 시스템 게시판이면 tenant_id 필터 없음 $query->where(function ($q) { + // 현재 테넌트 글 $q->where('tenant_id', $this->tenantId()) - ->orWhereHas('board', fn ($b) => $b->where('is_system', true)); + // 또는 시스템 게시판의 본사 글 + ->orWhere(function ($sub) { + $sub->where('tenant_id', self::HQ_TENANT_ID) + ->whereHas('board', fn ($b) => $b->where('is_system', true)); + }); }); } elseif ($isSystemBoard) { - // 시스템 게시판: tenant_id 필터 없음 + // 시스템 게시판: 본사 글 + 현재 테넌트 글 + $this->applySystemBoardScope($query); } else { $query->where('tenant_id', $this->tenantId()); } @@ -435,9 +487,11 @@ public function deletePostByBoardCode(string $boardCode, int $postId): bool $query = Post::where('board_id', $board->id); - // 시스템 게시판: tenant_id 필터 없음 + // 시스템 게시판: 본사 글 + 현재 테넌트 글 // 일반 게시판: 현재 테넌트 게시글만 - if (! $board->is_system) { + if ($board->is_system) { + $this->applySystemBoardScope($query); + } else { $query->where('tenant_id', $this->tenantId()); } @@ -464,7 +518,12 @@ public function deletePostBySystemBoardCode(string $boardCode, int $postId): boo return false; } - $post = Post::where('board_id', $board->id)->find($postId); + $query = Post::where('board_id', $board->id); + + // 시스템 게시판: 본사 글 + 현재 테넌트 글 + $this->applySystemBoardScope($query); + + $post = $query->find($postId); if (! $post) { return false; @@ -521,6 +580,7 @@ public function getComments(int $postId): Collection public function createComment(int $postId, array $data): BoardComment { $data['post_id'] = $postId; + $data['tenant_id'] = $this->tenantId(); $data['user_id'] = $this->apiUserId(); $data['ip_address'] = request()->ip(); $data['status'] = 'active'; @@ -569,10 +629,26 @@ public function deleteComment(int $commentId): bool /** * 커스텀 필드 값 저장 + * + * @param int $postId 게시글 ID + * @param int $boardId 게시판 ID (field_key → field_id 변환용) + * @param array $customFields [field_key => value] 또는 [field_id => value] */ - protected function saveCustomFields(int $postId, array $customFields): void + protected function saveCustomFields(int $postId, int $boardId, array $customFields): void { - foreach ($customFields as $fieldId => $value) { + // field_key → field_id 매핑 조회 + $fieldMap = \App\Models\Boards\BoardSetting::where('board_id', $boardId) + ->pluck('id', 'field_key') + ->toArray(); + + foreach ($customFields as $fieldKey => $value) { + // field_key가 문자열이면 field_id로 변환 + $fieldId = is_numeric($fieldKey) ? (int) $fieldKey : ($fieldMap[$fieldKey] ?? null); + + if ($fieldId === null) { + continue; // 존재하지 않는 필드는 무시 + } + PostCustomFieldValue::updateOrCreate( [ 'post_id' => $postId, @@ -601,16 +677,12 @@ public function getCustomFieldValues(int $postId): Collection /** * 나의 게시글 목록 조회 - * 시스템 게시판(tenant_id = null) 및 테넌트 게시판의 게시글 모두 조회 + * 현재 테넌트에서 내가 작성한 게시글 조회 */ public function getMyPosts(array $filters = [], int $perPage = 15): LengthAwarePaginator { return Post::where('user_id', $this->apiUserId()) - ->where(function ($q) { - // 시스템 게시판 게시글 또는 현재 테넌트 게시글 - $q->whereNull('tenant_id') - ->orWhere('tenant_id', $this->tenantId()); - }) + ->where('tenant_id', $this->tenantId()) ->with(['board:id,board_code,name,is_system']) ->when(isset($filters['board_code']), function ($q) use ($filters) { $q->whereHas('board', fn ($query) => $query->where('board_code', $filters['board_code']));