Files
sam-api/app/Services/Boards/BoardService.php

379 lines
10 KiB
PHP
Raw Permalink Normal View History

<?php
namespace App\Services\Boards;
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;
class BoardService extends Service
{
// =========================================================================
// 조회 메서드
// =========================================================================
/**
* 접근 가능한 게시판 목록 (시스템 + 테넌트)
*/
public function getAccessibleBoards(array $filters = []): Collection
{
return Board::accessible($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('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;
}
}