fix: 게시판 시스템 tenant_id 및 custom_fields 처리 개선
- 시스템 게시판도 tenant_id 항상 설정 (본사=1 글만 전체 공개) - applySystemBoardScope() 헬퍼 추가로 쿼리 조건 통일 - saveCustomFields()에 field_key → field_id 매핑 로직 추가 - createComment()에 tenant_id 추가 (NOT NULL 제약조건 충족) - 시스템 게시판 조회 조건: (tenant_id = 1) OR (tenant_id = 현재테넌트) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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']));
|
||||
|
||||
Reference in New Issue
Block a user