chore: 문서 및 설정 파일 업데이트

- LOGICAL_RELATIONSHIPS.md 업데이트
- 한국어 메시지 파일 업데이트
- API 라우트 정비
- CURRENT_WORKS.md 업데이트
This commit is contained in:
2025-11-30 21:06:22 +09:00
parent 3c9ba94784
commit d60a29fb10
4 changed files with 174 additions and 8 deletions

View File

@@ -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 보완
### 작업 목표

View File

@@ -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`

View File

@@ -37,6 +37,7 @@
'created' => '품목이 등록되었습니다.',
'updated' => '품목이 수정되었습니다.',
'deleted' => '품목이 삭제되었습니다.',
'batch_deleted' => '품목이 일괄 삭제되었습니다.',
],
'product' => [

View File

@@ -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 그룹 밖)