From d60a29fb107e2d99b0cc61656e5d822bc7c6df7e Mon Sep 17 00:00:00 2001 From: hskwon Date: Sun, 30 Nov 2025 21:06:22 +0900 Subject: [PATCH] =?UTF-8?q?chore:=20=EB=AC=B8=EC=84=9C=20=EB=B0=8F=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LOGICAL_RELATIONSHIPS.md 업데이트 - 한국어 메시지 파일 업데이트 - API 라우트 정비 - CURRENT_WORKS.md 업데이트 --- CURRENT_WORKS.md | 138 +++++++++++++++++++++++++++++++++++++++ LOGICAL_RELATIONSHIPS.md | 3 +- lang/ko/message.php | 1 + routes/api.php | 40 ++++++++++-- 4 files changed, 174 insertions(+), 8 deletions(-) diff --git a/CURRENT_WORKS.md b/CURRENT_WORKS.md index 3483061..58b79f1 100644 --- a/CURRENT_WORKS.md +++ b/CURRENT_WORKS.md @@ -1,5 +1,143 @@ # SAM API 작업 현황 +## 2025-11-27 (수) - 시스템 게시판 기능 확장 + +### 작업 목표 +- 기존 boards 테이블에 시스템 게시판 지원 추가 +- mng에서 시스템 게시판 생성, sam에서 테넌트 게시판 + 시스템 게시판 조회 + +### 수정된 파일 + +**Migration**: +- `database/migrations/2025_11_27_205429_add_system_fields_to_boards_table.php` (NEW) + - `tenant_id` nullable 변경 + - `is_system` boolean 컬럼 추가 + - `board_type` VARCHAR(50) 컬럼 추가 + - `deleted_at`, `deleted_by` SoftDeletes 추가 + - 인덱스 추가 + +**Model**: +- `app/Models/Boards/Board.php` + - SoftDeletes 추가 + - fillable, casts 업데이트 + - `scopeAccessible(tenantId)`, `scopeSystemOnly()`, `scopeTenantOnly(tenantId)` 스코프 추가 + - 권한 헬퍼 메서드 (canRead, canWrite, canManage) + +- `app/Models/Boards/BoardSetting.php` + - casts, fillable 업데이트 + - getMeta() 헬퍼 추가 + +**Service**: +- `app/Services/Boards/BoardService.php` (NEW) + - 시스템/테넌트 게시판 CRUD + - 필드 관리 (add, update, delete, reorder) + - 유틸리티 메서드 + +### DB 스키마 변경 + +```sql +-- boards 테이블 추가 컬럼 +is_system TINYINT(1) DEFAULT 0 COMMENT '시스템 게시판 여부' +board_type VARCHAR(50) NULL COMMENT '게시판 유형' +deleted_at TIMESTAMP NULL +deleted_by BIGINT UNSIGNED NULL +``` + +### 다음 작업 +- mng 게시판 관리 화면 개발 ✅ +- sam API 개발 (Swagger 포함) ✅ +- 검증 및 테스트 ✅ + +--- + +## 2025-11-27 (수) - sam API 게시판/게시글 API 개발 + +### 작업 목표 +- 테넌트용 게시판/게시글 V1 API 개발 +- Swagger 문서 작성 + +### 추가된 파일 + +**Service**: +- `app/Services/Boards/PostService.php` (NEW) + - 게시글 CRUD (boardCode 기반) + - 댓글 CRUD + - 커스텀 필드 관리 + - 조회수 증가 + +**Controller**: +- `app/Http/Controllers/Api/V1/BoardController.php` (NEW) + - index: 접근 가능한 게시판 목록 (시스템 + 테넌트) + - tenantBoards: 테넌트 게시판만 + - show: 게시판 상세 (코드 기반) + - store/update/destroy: 테넌트 게시판 CRUD + - fields: 게시판 필드 목록 + +- `app/Http/Controllers/Api/V1/PostController.php` (NEW) + - index/show/store/update/destroy: 게시글 CRUD + - comments/storeComment/updateComment/destroyComment: 댓글 CRUD + +**FormRequest**: +- `app/Http/Requests/Boards/BoardStoreRequest.php` (NEW) +- `app/Http/Requests/Boards/BoardUpdateRequest.php` (NEW) +- `app/Http/Requests/Boards/PostStoreRequest.php` (NEW) +- `app/Http/Requests/Boards/PostUpdateRequest.php` (NEW) +- `app/Http/Requests/Boards/CommentStoreRequest.php` (NEW) + +**Swagger**: +- `app/Swagger/v1/BoardApi.php` (NEW) + - Board, BoardField 스키마 + - BoardCreateRequest, BoardUpdateRequest 스키마 + - 7개 엔드포인트 문서화 + +- `app/Swagger/v1/PostApi.php` (NEW) + - Post, PostPagination, Comment 스키마 + - PostCreateRequest, PostUpdateRequest, CommentCreateRequest 스키마 + - 9개 엔드포인트 문서화 + +### 수정된 파일 +- `routes/api.php` + - BoardController, PostController import 추가 + - /v1/boards 프리픽스로 16개 라우트 등록 + +### API 엔드포인트 (16개) + +**게시판 관리**: +| Method | Path | 설명 | +|--------|------|------| +| GET | /v1/boards | 접근 가능한 게시판 목록 | +| GET | /v1/boards/tenant | 테넌트 게시판만 | +| POST | /v1/boards | 테넌트 게시판 생성 | +| GET | /v1/boards/{code} | 게시판 상세 (코드 기반) | +| PUT | /v1/boards/{id} | 테넌트 게시판 수정 | +| DELETE | /v1/boards/{id} | 테넌트 게시판 삭제 | +| GET | /v1/boards/{code}/fields | 게시판 필드 목록 | + +**게시글 관리**: +| Method | Path | 설명 | +|--------|------|------| +| GET | /v1/boards/{code}/posts | 게시글 목록 | +| POST | /v1/boards/{code}/posts | 게시글 작성 | +| GET | /v1/boards/{code}/posts/{id} | 게시글 상세 | +| PUT | /v1/boards/{code}/posts/{id} | 게시글 수정 | +| DELETE | /v1/boards/{code}/posts/{id} | 게시글 삭제 | + +**댓글 관리**: +| Method | Path | 설명 | +|--------|------|------| +| GET | /v1/boards/{code}/posts/{postId}/comments | 댓글 목록 | +| POST | /v1/boards/{code}/posts/{postId}/comments | 댓글 작성 | +| PUT | /v1/boards/{code}/posts/{postId}/comments/{commentId} | 댓글 수정 | +| DELETE | /v1/boards/{code}/posts/{postId}/comments/{commentId} | 댓글 삭제 | + +### 검증 결과 +- PHP 문법 검사: ✅ 통과 +- Pint 코드 포맷팅: ✅ 완료 +- Swagger 문서 생성: ✅ 완료 +- 라우트 등록: ✅ 16개 라우트 확인 + +--- + ## 2025-11-27 (수) - ItemMaster API group_id(계층번호) 추가 및 Swagger 보완 ### 작업 목표 diff --git a/LOGICAL_RELATIONSHIPS.md b/LOGICAL_RELATIONSHIPS.md index d2458cb..7a3fbe9 100644 --- a/LOGICAL_RELATIONSHIPS.md +++ b/LOGICAL_RELATIONSHIPS.md @@ -1,6 +1,6 @@ # 논리적 데이터베이스 관계 문서 -> **자동 생성**: 2025-11-27 15:34:54 +> **자동 생성**: 2025-11-28 17:41:00 > **소스**: Eloquent 모델 관계 분석 ## 📊 모델별 관계 현황 @@ -137,7 +137,6 @@ ### entity_relationships ### item_pages **모델**: `App\Models\ItemMaster\ItemPage` -- **sections()**: hasMany → `item_sections` - **sectionRelationships()**: hasMany → `entity_relationships` - **fieldRelationships()**: hasMany → `entity_relationships` - **allRelationships()**: hasMany → `entity_relationships` diff --git a/lang/ko/message.php b/lang/ko/message.php index 0789266..994c5d2 100644 --- a/lang/ko/message.php +++ b/lang/ko/message.php @@ -37,6 +37,7 @@ 'created' => '품목이 등록되었습니다.', 'updated' => '품목이 수정되었습니다.', 'deleted' => '품목이 삭제되었습니다.', + 'batch_deleted' => '품목이 일괄 삭제되었습니다.', ], 'product' => [ diff --git a/routes/api.php b/routes/api.php index 122090c..1c5a855 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,7 @@ use App\Http\Controllers\Api\V1\AdminController; use App\Http\Controllers\Api\V1\ApiController; +use App\Http\Controllers\Api\V1\BoardController; use App\Http\Controllers\Api\V1\CategoryController; use App\Http\Controllers\Api\V1\CategoryFieldController; use App\Http\Controllers\Api\V1\CategoryLogController; @@ -32,6 +33,7 @@ use App\Http\Controllers\Api\V1\MenuController; use App\Http\Controllers\Api\V1\ModelSetController; use App\Http\Controllers\Api\V1\PermissionController; +use App\Http\Controllers\Api\V1\PostController; use App\Http\Controllers\Api\V1\PricingController; use App\Http\Controllers\Api\V1\ProductBomItemController; use App\Http\Controllers\Api\V1\ProductController; @@ -349,12 +351,13 @@ Route::post('', [\App\Http\Controllers\Api\V1\ItemsController::class, 'store'])->name('v1.items.store'); // 품목 생성 Route::get('/code/{code}', [\App\Http\Controllers\Api\V1\ItemsController::class, 'showByCode'])->name('v1.items.show_by_code'); // code 기반 조회 Route::get('/{id}', [\App\Http\Controllers\Api\V1\ItemsController::class, 'show'])->name('v1.items.show'); // 단건 (item_type 파라미터 필수) - Route::put('/{code}', [\App\Http\Controllers\Api\V1\ItemsController::class, 'update'])->name('v1.items.update'); // 품목 수정 - Route::delete('/{code}', [\App\Http\Controllers\Api\V1\ItemsController::class, 'destroy'])->name('v1.items.destroy'); // 품목 삭제 + Route::put('/{id}', [\App\Http\Controllers\Api\V1\ItemsController::class, 'update'])->name('v1.items.update'); // 품목 수정 + Route::delete('/{id}', [\App\Http\Controllers\Api\V1\ItemsController::class, 'destroy'])->name('v1.items.destroy'); // 품목 삭제 + Route::delete('/batch', [\App\Http\Controllers\Api\V1\ItemsController::class, 'batchDestroy'])->name('v1.items.batch_destroy'); // 품목 일괄 삭제 }); - // Items BOM (Code-based BOM API - adapter for frontend) - Route::prefix('items/{code}/bom')->group(function () { + // Items BOM (ID-based BOM API) + Route::prefix('items/{id}/bom')->group(function () { Route::get('', [\App\Http\Controllers\Api\V1\ItemsBomController::class, 'index'])->name('v1.items.bom.index'); // BOM 목록 (flat) Route::get('/tree', [\App\Http\Controllers\Api\V1\ItemsBomController::class, 'tree'])->name('v1.items.bom.tree'); // BOM 트리 (계층) Route::post('', [\App\Http\Controllers\Api\V1\ItemsBomController::class, 'store'])->name('v1.items.bom.store'); // BOM 추가 (bulk) @@ -367,8 +370,8 @@ Route::get('/categories', [\App\Http\Controllers\Api\V1\ItemsBomController::class, 'listCategories'])->name('v1.items.bom.categories'); // 카테고리 목록 }); - // Items Files (Code-based File Upload API) - Route::prefix('items/{code}/files')->group(function () { + // Items Files (ID-based File Upload API) + Route::prefix('items/{id}/files')->group(function () { Route::post('', [\App\Http\Controllers\Api\V1\ItemsFileController::class, 'upload'])->name('v1.items.files.upload'); // 파일 업로드 Route::delete('/{type}', [\App\Http\Controllers\Api\V1\ItemsFileController::class, 'delete'])->name('v1.items.files.delete'); // 파일 삭제 (type: bending_diagram|specification|certification) }); @@ -568,6 +571,31 @@ Route::post('/relationships/reorder', [EntityRelationshipController::class, 'reorderRelationships'])->name('v1.item-master.relationships.reorder'); }); + // 게시판 관리 API (테넌트용) + Route::prefix('boards')->group(function () { + // 게시판 목록/상세 + Route::get('/', [BoardController::class, 'index'])->name('v1.boards.index'); // 접근 가능한 게시판 목록 + Route::get('/tenant', [BoardController::class, 'tenantBoards'])->name('v1.boards.tenant'); // 테넌트 게시판만 + Route::post('/', [BoardController::class, 'store'])->name('v1.boards.store'); // 테넌트 게시판 생성 + Route::get('/{code}', [BoardController::class, 'show'])->name('v1.boards.show'); // 게시판 상세 (코드 기반) + Route::put('/{id}', [BoardController::class, 'update'])->whereNumber('id')->name('v1.boards.update'); // 테넌트 게시판 수정 + Route::delete('/{id}', [BoardController::class, 'destroy'])->whereNumber('id')->name('v1.boards.destroy'); // 테넌트 게시판 삭제 + Route::get('/{code}/fields', [BoardController::class, 'fields'])->name('v1.boards.fields'); // 게시판 필드 목록 + + // 게시글 API + Route::get('/{code}/posts', [PostController::class, 'index'])->name('v1.boards.posts.index'); // 게시글 목록 + Route::post('/{code}/posts', [PostController::class, 'store'])->name('v1.boards.posts.store'); // 게시글 작성 + Route::get('/{code}/posts/{id}', [PostController::class, 'show'])->name('v1.boards.posts.show'); // 게시글 상세 + Route::put('/{code}/posts/{id}', [PostController::class, 'update'])->name('v1.boards.posts.update'); // 게시글 수정 + Route::delete('/{code}/posts/{id}', [PostController::class, 'destroy'])->name('v1.boards.posts.destroy'); // 게시글 삭제 + + // 댓글 API + Route::get('/{code}/posts/{postId}/comments', [PostController::class, 'comments'])->name('v1.boards.posts.comments.index'); // 댓글 목록 + Route::post('/{code}/posts/{postId}/comments', [PostController::class, 'storeComment'])->name('v1.boards.posts.comments.store'); // 댓글 작성 + Route::put('/{code}/posts/{postId}/comments/{commentId}', [PostController::class, 'updateComment'])->name('v1.boards.posts.comments.update'); // 댓글 수정 + Route::delete('/{code}/posts/{postId}/comments/{commentId}', [PostController::class, 'destroyComment'])->name('v1.boards.posts.comments.destroy'); // 댓글 삭제 + }); + }); // 공유 링크 다운로드 (인증 불필요 - auth.apikey 그룹 밖)