docs(menu): 사이드바 권한 동기화 지침 추가

- frontend_backend_alignment_report.md에 사이드바/그룹 권한 TODO와 테스트 계획을 정리
- stock_approval_system_api_v4.md에 메뉴/그룹 권한 API 규칙과 응답 예시를 추가
- stock_approval_system_spec_v4.md에 공식 메뉴 표와 기본 그룹 권한 케이스를 기재
This commit is contained in:
JiWoong Sul
2025-11-12 00:27:17 +09:00
parent eaac3c23ae
commit f767c44573
3 changed files with 84 additions and 0 deletions

View File

@@ -59,6 +59,18 @@
- `GET /api/v1/group-menu-permissions``include_deleted`를 허용하고 `route_path`, `path`, `is_deleted`를 응답에 포함한다. 프런트 DTO와 편집 화면이 삭제 항목을 구분 표시하는지 확인한다. - `GET /api/v1/group-menu-permissions``include_deleted`를 허용하고 `route_path`, `path`, `is_deleted`를 응답에 포함한다. 프런트 DTO와 편집 화면이 삭제 항목을 구분 표시하는지 확인한다.
- 백엔드/프런트 문서가 모두 최신 스펙을 참조하도록, `backend_change_requests.md`와 프런트 대응 문서를 동시에 업데이트한 후 공유한다. - 백엔드/프런트 문서가 모두 최신 스펙을 참조하도록, `backend_change_requests.md`와 프런트 대응 문서를 동시에 업데이트한 후 공유한다.
## 사이드바 & 메뉴 권한
- 백엔드 `menus` 테이블이 사이드바 18개 항목과 1:1 매핑되도록 `menu_code / route_path / display_order`가 고정됐다. 스펙·API 문서에 표가 추가됐으므로 프런트 문서도 동일 표를 참조한다.
- `group_menu_permissions` 응답은 삭제 메뉴를 숨기므로, 드롭다운 리스트 역시 서버 응답 기준으로 렌더링해야 한다. 기존 로컬 enum은 제거한다.
- 로그인 세션 `permissions[].resource``route_path` 값을 사용하므로, 사이드바 렌더링은 `menu_code ↔ route_path` 매퍼만 유지하면 된다.
### 프런트엔드 작업
1. **사이드바 소스 통합**`GET /menus?active=true&include=parent` 응답을 불러와 `SidebarSection`을 구성하고, `display_order` 순서를 그대로 따른다.
2. **그룹 권한 드롭다운 개편** — 권한 편집 화면에서 동일 메뉴 데이터를 트리형 선택 UI로 노출하고, `include_deleted` 케이스에 회색/비활성 스타일을 적용한다.
3. **권한 기반 렌더링 보강** — 로그인 세션 `permissions` + 메뉴 데이터를 조합해 그룹별 사이드바 노출을 제어하고, 관리자/결재 담당자/일반 사용자 시나리오에 대한 스냅샷 테스트를 추가한다.
4. **문서/DTO 동기화**`tool/sync_stock_docs.sh` 실행 후 `doc/frontend_api_alignment_plan.md` 등에 새 메뉴 표와 라우트 매핑 규칙을 기록한다.
5. **회귀 테스트** — 그룹 메뉴 권한 수정 → 재로그인 플로우를 E2E 테스트에 추가해 라우트/사이드바 반영 여부를 검증한다.
## 일정 & 의존성 ## 일정 & 의존성
| 구분 | 작업 내용 | 담당 | 상태 | 목표일(제안) | 비고 | | 구분 | 작업 내용 | 담당 | 상태 | 목표일(제안) | 비고 |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |

View File

@@ -514,6 +514,46 @@
--- ---
### 3.9 메뉴 & 그룹 권한
- **목적:** 프런트 사이드바/권한 편집 화면에서 동일한 메뉴 목록을 재사용하기 위한 단일 소스.
- **엔드포인트:** `GET /menus`, `POST /menus`, `PATCH /menus/{id}`, `DELETE /menus/{id}`, `GET /group-menu-permissions`.
- **정렬 규칙:** `parent_menu_id ASC`, `display_order ASC`.
- **필수 필드:** `menu_code`, `menu_name`, `parent_menu_id`, `route_path`, `display_order`.
- **삭제 정책:** UI에서 제거된 메뉴는 `is_deleted=true`로만 남겨두며 기본 응답에서는 제외한다. 필요 시 `include_deleted=true`로 조회해 비활성 메뉴를 회색 처리한다.
`GET /menus?active=true&include=parent&order=asc`
```json
{
"items": [
{
"id": 10,
"menu_code": "inventory.receipts",
"menu_name": "입고",
"parent_menu_id": 2,
"route_path": "/inventory/receipts",
"display_order": 10,
"note": "입고 전표/입고 처리",
"is_active": true,
"created_at": "2025-11-11T12:00:00Z",
"updated_at": "2025-11-11T12:00:00Z",
"parent": {
"id": 2,
"menu_code": "inventory",
"menu_name": "재고/입출고",
"route_path": "/inventory"
}
}
],
"page": 1,
"page_size": 50,
"total": 18
}
```
권한 편집 시 `group_menu_permissions``menu` 객체는 항상 `menu_code`, `menu_name`, `route_path`, `is_deleted`를 포함하며, UI는 이 값을 그대로 드롭다운/트리 항목으로 사용해야 한다. 메뉴 추가/삭제는 먼저 `menus`에 반영한 뒤 각 그룹 권한을 업데이트해야 하며, `menu_code`는 프런트 라우트 키와 반드시 동일해야 한다.
---
## 4. 트랜잭션/재고 API ## 4. 트랜잭션/재고 API
리소스: `/stock-transactions`, 보조 리소스: `/transaction-lines`, `/transaction-customers` 리소스: `/stock-transactions`, 보조 리소스: `/transaction-lines`, `/transaction-customers`

View File

@@ -259,6 +259,35 @@ zipcodes ||--o{ customers : addressed
| updated_at | 변경일시 | timestamp | - | now() | Y | | | | | updated_at | 변경일시 | timestamp | - | now() | Y | | | |
> 메뉴는 계층 구조를 지원하며 `parent_menu_id`가 NULL이면 1차 메뉴로 간주. > 메뉴는 계층 구조를 지원하며 `parent_menu_id`가 NULL이면 1차 메뉴로 간주.
> 프런트엔드 사이드바와 1:1로 매칭되는 공식 메뉴 목록은 다음과 같다.
>
> | menu_code | parent_code | menu_name | route_path | display_order | 설명 |
> | --- | --- | --- | --- | --- | --- |
> | `dashboard` | - | 대시보드 | `/dashboard` | 10 | KPI/요약 카드 |
> | `inventory` | - | 재고/입출고 | `/inventory` | 20 | 재고 섹션 루트 |
> | `inventory.receipts` | `inventory` | 입고 | `/inventory/receipts` | 10 | 입고 전표 |
> | `inventory.issues` | `inventory` | 출고 | `/inventory/issues` | 20 | 출고 전표 |
> | `inventory.rentals` | `inventory` | 대여 | `/inventory/rentals` | 30 | 대여/반납 전표 |
> | `inventory.manufacturers` | `inventory` | 제조사 관리 | `/inventory/manufacturers` | 40 | 벤더/제조사 |
> | `inventory.models` | `inventory` | 장비 모델 관리 | `/inventory/models` | 50 | 제품/장비 모델 |
> | `inventory.warehouses` | `inventory` | 입고지 관리 | `/inventory/warehouses` | 60 | 창고/입고지 |
> | `inventory.customers` | `inventory` | 회사 관리 | `/inventory/customers` | 70 | 고객/거래처 |
> | `settings` | - | 설정 | `/settings` | 30 | 사용자/권한 섹션 루트 |
> | `settings.users` | `settings` | 사용자 관리 | `/settings/users` | 10 | 사용자 CRUD |
> | `settings.groups` | `settings` | 그룹 관리 | `/settings/groups` | 20 | 그룹 CRUD |
> | `settings.menus` | `settings` | 메뉴 관리 | `/settings/menus` | 30 | 메뉴 마스터 관리 |
> | `settings.group_permissions` | `settings` | 그룹 메뉴 권한 | `/settings/group-permissions` | 40 | 그룹별 메뉴 권한 |
> | `approvals` | - | 결재 | `/approvals` | 40 | 결재 섹션 루트 |
> | `approvals.requests` | `approvals` | 결재 관리 | `/approvals/requests` | 10 | 결재 요청 목록 |
> | `approvals.steps` | `approvals` | 결재 단계 | `/approvals/steps` | 20 | 결재 단계 관리 |
> | `approvals.history` | `approvals` | 결재 이력 | `/approvals/history` | 30 | 결재 이력 |
> | `approvals.templates` | `approvals` | 결재 템플릿 | `/approvals/templates` | 40 | 템플릿 관리 |
> | `utilities` | - | 유틸리티 | `/utilities` | 50 | 보조 기능 루트 |
> | `utilities.zipcodes` | `utilities` | 우편번호 검색 | `/utilities/zipcodes` | 10 | 주소/우편번호 검색 |
> | `reports` | - | 보고서 | `/reports` | 60 | 보고서 루트 |
> | `reports.overview` | `reports` | 보고서 | `/reports` | 10 | 보고서 요약/다운로드 |
>
> 위 목록 외 메뉴 코드는 모두 `is_deleted=true`로 유지해 사이드바/드롭다운에 노출되지 않는다.
--- ---
@@ -304,6 +333,9 @@ zipcodes ||--o{ customers : addressed
| updated_at | 변경일시 | timestamp | - | now() | Y | | | | | updated_at | 변경일시 | timestamp | - | now() | Y | | | |
> 각 메뉴에 대한 CRUD 권한을 그룹 단위로 정의하며, 권한 미설정 시 기본적으로 조회만 허용. > 각 메뉴에 대한 CRUD 권한을 그룹 단위로 정의하며, 권한 미설정 시 기본적으로 조회만 허용.
> 기본 그룹 권한 예시:
> - `전사 관리자`: `menus` 테이블에 남아 있는 모든 메뉴에 대해 `can_create=can_read=can_update=can_delete=true`.
> - `결재 담당자`(`approval.manage` 스코프 보유): `dashboard`, `inventory.receipts|issues|rentals`, `approvals.requests`, `approvals.steps`, `approvals.history`, `approvals.templates`만 노출되며, `approvals*` 계열 메뉴에 한해 `can_create=true`, `can_update=true`가 부여된다. 기타 메뉴 권한은 `is_deleted=true`로 비활성화해 UI/엔드포인트 모두 접근이 차단된다.
--- ---