파일
wbx-spring/plans/wtmgr/11-requirements-traceability.md
accura0117 9707a6eeb1 feat: FE 화면 구현 완료 + 샘플 데이터 + 결재라인 연동
- WBS/TEAL 화면 실제 구현 (TreeTable, FileUpload, 버전관리)
- 시수이력/결재이력 화면 구현 (DataTable, Filter, Timeline)
- 비밀번호변경 화면 추가
- 로그인 snake_case 응답 매핑 수정
- Vite 프록시 8081 포트 수정
- auth guard에서 fetchMe 자동 호출
- V108 샘플 데이터 (10명 사용자, 4주 시수 215건, 결재 9건)
- 배너 추가 (WBX Spring)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 22:17:32 +09:00

935 줄
41 KiB
Markdown
Raw Blame 히스토리

이 파일에는 모호한 유니코드 문자가 포함되어 있습니다
이 파일에는 다른 문자와 혼동될 수 있는 유니코드 문자가 포함되어 있습니다. 의도적인 것이라고 생각되면 이 경고를 무시해도 됩니다. Escape 버튼을 눌러 표시할 수 있습니다.
# 11. 요구사항 추적표 (requierment.xlsx 기반)
> 원본: `d:\sc\requierment.xlsx` — 기능 86개 + 비기능 17개 + 확인필요사항 7건
> 수정일: 2026-03-25
---
## 0. 기능 요구사항 전체 매핑표
> PH1 Y/N은 Excel "Phase 1 (Y/N)" 컬럼 기준
### User Registration (No.1~7)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 1 | 기준정보 | SAP SF HR Master 파일 업로드 | Y | 08-sap | PH1 수동 업로드 |
| 2 | 기준정보 | 내부 인력 필드 (사번~Part 5레벨) Read-only | Y | 02-db | users 테이블 |
| 3 | 기준정보 | 정기 배치 자동 업데이트 | N | 08-sap | PH2: 안정화 후 |
| 4 | 기준정보 | 외주 인력 파일 업로드 (표준 템플릿) | Y | 07-api | 확인필요사항#1 |
| 5 | 기준정보 | 외주 인력 개별 입력창 | N | - | PH2: 정책 미확정 |
| 6 | 기준정보 | 파일 업로드는 SA가 관리 | Y | 07-api | SA 권한 |
| 7 | 기준정보 | 외부 사용자 최소 정보 (회사명~내부담당자) | Y | 02-db | users 테이블 확장 |
### Login (No.8~16)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 8 | 로그인 | 내부 사용자 ID/PW 로그인 | Y | wbx-spring | AuthController |
| 9 | 로그인 | 외부 사용자 2Way 인증 | N | - | PH2: 외주 포털 후 |
| 10 | 로그인 | ID/PW 찾기 기능 | Y | wbx-spring | PasswordPolicy |
| 11 | 로그인 | ID = 사번 (오션 표준) | Y | 02-db | employee_number |
| 12 | 로그인 | PW 정책 (대소문자+특수문자) | Y | wbx-spring | PasswordPolicy |
| 13 | 로그인 | PW 입력 시 "*" 마스킹 | Y | FE 기본 | - |
| 14 | 로그인 | PW 주기적 재설정 | Y | wbx-spring | expiryDays |
| 15 | 로그인 | PW 5회 실패 시 재설정 프로세스 | Y | wbx-spring | maxFailedAttempts |
| 16 | Interface | SSO (Entra ID) 적용 | Y | wbx-spring | SsoSuccessHandler |
### User Home (No.17~24)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 17 | 권한관리 | 권한별 홈 페이지 라우팅 | Y | 07-api | 확인필요사항#2 |
| 18 | 사용자등급 | 6종 역할 (SA/PM/PCM/PTK/DL/User) | Y | 02-db | roles 테이블 |
| 19 | 사용자등급 | SA 전체 기능 컨트롤 | N | - | PH2: 보안 감사용 |
| 20 | 사용자등급 | PM 권한 (WBS/Member/승인) | Y | 05-approval | |
| 21 | 사용자등급 | PCM/PTK 권한 (WBS Task 배정) | Y | 04-wbs | |
| 22 | 사용자등급 | User 할당 Project/WBS만 조회 | Y | 03-timesheet | |
| 23 | 사용자등급 | DL 결재 권한 (조직원 Timesheet) | Y | 05-approval | DL 정책 TBD |
| 24 | 사용자등급 | SA 접속/Activity 로그 관리 | N | - | PH2: 보안 감사 |
### Project Registration (No.25~30)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 25 | PJT Creation | 프로젝트 생성 절차 (PM/PCM→SA 승인) | Y | 07-api | |
| 26 | PJT Creation | Project Type 3종 (Non/Other/EPC) | Y | 02-db | project_type |
| 27 | PJT Creation | Canonical WBS 파일 업로드→PM 승인 | Y | 04-wbs | |
| 28 | PJT Edit | 변경 WBS 신규 파일 업로드 | Y | 04-wbs | |
| 29 | PJT Edit | WBS 버전 관리/비교 | N | 04-wbs | PH1-2차 |
| 30 | PJT Edit | 기존 WBS 시수 조회 | N | - | PH2: No.29 연계 |
### WBS Upload (No.31~41)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 31 | P6 WBS | WBS L5 + Activity 정보 접수 | Y | 04-wbs | P6WbsParser |
| 32 | P6 WBS | 월단위 Snapshot 비교 | N | - | PH2: 고도화 |
| 33 | Canonical WBS | 표준 WBS, Project별 수정 불가 | Y | 04-wbs | |
| 34 | Canonical WBS | WBS 5레벨 구조 (L1~L5) | Y | 04-wbs | |
| 35 | Canonical WBS | WBS Upload 5단계 절차 | Y | 04-wbs | |
| 36 | WBS Versioning | Effective 날짜 기준 버전 등록 | Y | 04-wbs | |
| 37 | WBS Versioning | 종결/폐기 Mapping 사용불가 처리 | Y | 04-wbs | |
| 38 | TEAL | TEAL 선정 기준 (MH투입/관리/측정 가능) | Y | 04-wbs | |
| 39 | TEAL | TEAL 선정 및 Upload 4단계 | Y | 04-wbs | |
| 40 | TEAL Versioning | 버전 정보 (Version/Date/승인/변경Log) | Y | 04-wbs | |
| 41 | TEAL Versioning | 과거 TT는 입력 당시 버전 유지 | Y | 04-wbs | |
### Resource Assignment (No.42~50)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 42 | Availability | SA가 기본 입력 기준 수정 | N | - | PH2: 확인필요사항#4 |
| 43 | Availability | 1일 최소 근무시간 8시간 | Y | 03-timesheet | RuleEngine |
| 44 | Availability | Activity 최소 1개 이상 | Y | 03-timesheet | |
| 45 | Availability | 주 최대 52시간, Location별 다름 | Y | 03-timesheet | RuleEngine |
| 46 | Availability | 초과근무/휴게시간 규칙 | N | - | PH2: 세부 규칙 UI |
| 47 | Project Assign | Discipline → Project Assign | Y | 07-api | |
| 48 | Project Assign | Non-Project는 별도 Assign 없이 전체 | Y | 03-timesheet | |
| 49 | Availability | Project별 Location/Job_Role 설정 | N | - | PH2: Unit Rate |
| 50 | WBS Assign | WBS-Discipline 자동 Assign | N | - | PH2: 방식 미확정 |
### My Project Setup (No.51~54)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 51 | Assigned PJT | Assign된 Project 정보 확인 | Y | 07-api | /my-projects |
| 52 | Assigned PJT | 프로젝트 상세 정보 조회 | Y | 07-api | |
| 53 | Assigned PJT | 권한별 정보 제한 | Y | wbx-spring | RBAC |
| 54 | Activity Setup | Favorite/Default 설정 | N | - | PH2: 편의 기능 |
### Time Sheet (No.55~69)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 55 | Non-Project | Overhead 최소 입력 (Type/Activity/Hour) | Y | 03-timesheet | NON_PROJECT |
| 56 | Non-Project | Overhead Type 4종 (수정 가능) | Y | 02-db | overhead_types |
| 57 | Non-Project | TEAL 기반 Activity 선택 | Y | 03-timesheet | |
| 58 | Non-Project | Resource Assignment 규칙 적용 | Y | 03-timesheet | RuleEngine |
| 59 | Non-Project | WBS/Project 정보 입력 불가 | Y | 03-timesheet | |
| 60 | Other Project | Tender/Pre-FEED/FEED/Internal 포함 | Y | 03-timesheet | OTHER_PROJECT |
| 61 | Other Project | 최소 입력 (PJT/WBS L2~4/Activity/Hour) | Y | 03-timesheet | |
| 62 | Other Project | P6 연동 불필요, Canonical WBS 사용 | Y | 04-wbs | |
| 63 | Other Project | Project별 Bench Marking | N | - | PH2: 데이터 축적 후 |
| 64 | EPC Project | EPC 필수 입력 (PJT/WBS L2~5/Activity/Hour) | Y | 03-timesheet | PH1-2차: Revision |
| 65 | EPC Project | Location/Role/진행률 추가 입력 | N | - | PH2: Unit Rate |
| 66 | EPC Project | P6 WBS 비노출, 할당 WBS만 선택 | Y | 03-timesheet | |
| 67 | 공통 | Remark 입력 (선택) | Y | 03-timesheet | |
| 68 | 공통 | Excel 템플릿 제공 + 임포트 | Y | 03-timesheet | |
| 69 | 공통 | 일자별 Activity별 1행, 합계 표시 | Y | 03-timesheet | |
### Approval (No.70~75+)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 70 | Process | Daily 입력, Weekly 승인, Alert | Y | 05-approval | |
| 71 | Process | User→DL→PM 3단계 승인 | Y | 05-approval | |
| 72 | Process | 승인/반려 + Comment | Y | 05-approval | |
| 73 | Process | 일괄 승인 | Y | 05-approval | |
| 74 | Process | 승인 이력 조회 | Y | 05-approval | |
| 75 | Process | 초과 기준 하이라이트 (min/max/OT) | Y | 05-approval | PH1-2차 |
### Reporting (No.76~86)
| No. | Category | 요구사항 요약 | PH1 | 계획서 | 비고 |
|-----|----------|-------------|:---:|--------|------|
| 76 | RCP연계 | RCP 연계 Plan vs Actual 분석 | N | - | PH2: RCP 시스템 미개발 |
| 77 | RCP연계 | RCP 연계 Capacity Gap 분석 | N | - | PH2: RCP 미개발 |
| 78 | RCP연계 | RCP 연계 Productivity Trend 분석 | N | - | PH2: RCP 미개발 |
| 79 | Version | WBS 버전 관리 + 이력 조회 | N | 04-wbs | PH2: 이력 조회 UI 협의 |
| 80 | Interface | Cognite 연계 데이터 Export | N | 08-sap | PH2: Extractor 서버 필요 |
| 81 | WBS 검토 | P6 WBS vs Canonical WBS Mis-Align 검토 | N | - | PH2: 운영 데이터 축적 후 |
| 82 | 일반 보고서 | Project별 투입 Manhour 분석 | Y | 06-report | PH1 기본 리포트 |
| 83 | 일반 보고서 | Canonical WBS Level별 Manhour 분석 | Y | 06-report | PH1 기본 리포트 |
| 84 | 일반 보고서 | Discipline별 생산성 분석 | N | - | PH2: Progress Rate 필요 |
| 85 | 일반 보고서 | Phase별 Manhour 비율 분석 | N | 06-report | PH1-2차 또는 PH2 협의 |
| 86 | 일반 보고서 | Non-Project Manhour 비율 분석 | N | 06-report | PH1-2차 또는 PH2 협의 |
### Non-Functional (NF.1~17)
| NF | Category | 요구사항 요약 | 계획서 |
|----|----------|-------------|--------|
| 1 | Cloud/Server | Azure Hybrid Security Zone | 09-devops |
| 2 | Cloud/Server | Azure IaaS 기반 | 09-devops |
| 3 | Security/Server | HIWARE, V3, Secuver TOS | 09-devops |
| 4 | Security/DB | Cubeone (TDE), Dbsafer (Proxy) | 09-devops |
| 5 | Security/Cloud | Defender + Analytics | 09-devops |
| 6 | Security/정보보호 | 보안 취약점 점검 (웹/모바일/서버/소스) | 09-devops |
| 7 | Security/정보보호 | 개인정보 보호 정책 준수 | 09-devops |
| 8 | Monitoring/Server | onTune (SMS), MCCS (HA) | 09-devops |
| 9 | Monitoring/DB | Maxguage (DB 모니터링) | 09-devops |
| 10 | Monitoring/App | Jennifer (APM) | 09-devops |
| 11 | Auth/Internal | Entra ID SSO | wbx-spring |
| 12 | Auth/External | 2Way 인증 (외부 사용자) | PH2 |
| 13 | Interface/HR | SAP BTP CPI (SuccessFactors) | 08-sap |
| 14 | Interface/P6 | P6 파일 기반 연동 (물리 I/F 없음) | 04-wbs |
| 15 | Interface/Cognite | Extractor 서버 필요 | PH2 |
| 16 | Architecture | HA 구성 (Web, WAS) | 09-devops |
| 17 | Architecture | 백업 전략 (시스템 복구) | 09-devops |
---
## 1. HR Master Data 필드 상세 (No.1~2)
SAP SuccessFactors에서 업로드되는 내부 인력 정보 필드. **Read-only**로 관리.
> **No.2 원문 (Eng)**: Employee Number, Employee Name, Business Unit (LV1), Division (LV2), Department (LV3), Discipline/Team (LV4), Part (LV5), Attendance Type, Individual Job Code
```sql
-- V1 보완: users 테이블 컬럼 (SAP SF 필드 매핑)
ALTER TABLE users ADD COLUMN employee_number VARCHAR(20); -- 사번 = 로그인 ID (No.11)
ALTER TABLE users ADD COLUMN business_unit VARCHAR(100); -- LV1: Business Unit
ALTER TABLE users ADD COLUMN division VARCHAR(100); -- LV2: Division
ALTER TABLE users ADD COLUMN department VARCHAR(100); -- LV3: Department
ALTER TABLE users ADD COLUMN discipline_team VARCHAR(100); -- LV4: Discipline/Team
ALTER TABLE users ADD COLUMN part VARCHAR(100); -- LV5: Part (★ 5레벨)
ALTER TABLE users ADD COLUMN attendance_type VARCHAR(50); -- 근태유형 (SAP SF)
ALTER TABLE users ADD COLUMN individual_job_code VARCHAR(50); -- 개인 직무코드 (SAP SF)
ALTER TABLE users ADD COLUMN job_role VARCHAR(100); -- Job Role
ALTER TABLE users ADD COLUMN grade VARCHAR(50); -- Grade/직급
ALTER TABLE users ADD COLUMN start_date DATE; -- 입사일
ALTER TABLE users ADD COLUMN end_date DATE; -- 종료일
ALTER TABLE users ADD COLUMN company_name VARCHAR(200); -- 외주: 회사명 (No.7)
ALTER TABLE users ADD COLUMN org_unit VARCHAR(200); -- 외주: 조직 정보 (No.7)
ALTER TABLE users ADD COLUMN internal_contact VARCHAR(200); -- 외주: 내부 담당자 정보 (No.7)
-- 조직 계층 테이블 (HR 데이터 정규화) — 5레벨
CREATE TABLE org_hierarchy (
id BIGINT IDENTITY PRIMARY KEY,
level INT NOT NULL, -- 1=BU, 2=Division, 3=Department, 4=Discipline/Team, 5=Part
code VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
parent_id BIGINT REFERENCES org_hierarchy(id),
is_active BIT DEFAULT 1,
UNIQUE (level, code)
);
```
### JPA Entity 보완
```java
@Entity @Table(name = "users")
public class User extends BaseEntity {
// ... 기존 필드 ...
@Column(length = 20, unique = true)
private String employeeNumber; // 사번 = 로그인 ID (No.11)
// 조직 4레벨 (SAP SF 기준)
private String businessUnit; // LV1
private String division; // LV2
private String department; // LV3
private String section; // LV4
private String discipline;
private String jobRole;
private String grade;
private LocalDate startDate;
private LocalDate endDate;
// 외주 전용 (No.7)
private String companyName;
private String internalContact;
@Enumerated(EnumType.STRING)
@Column(length = 20)
private EmploymentType employmentType; // INTERNAL, SUBCONTRACTOR
}
```
---
## 2. Non-Project Overhead 유형 상세 (No.55~59)
요구사항 No.56에서 명시된 Overhead Type. **SA가 수정 가능**해야 함.
```java
// 시스템 초기 Overhead Types (No.56 — 영문 원본 기준, 향후 수정 가능)
// ★ 기존 계획서의 9종 → 원본 4종으로 수정
public enum OverheadType {
TRAINING("Training", "Employee education and competency development activities"),
SYSTEM_PROCESS_DEV("System and Process Development", "System and process development and improvement activities"),
ORG_OPERATION("Organizational Operation", "Internal organizational administrative tasks"),
CORPORATE_INITIATIVE("Corporate Initiative or Strategy", "Executive-led corporate strategic initiatives");
// ★ Leave, Sick Leave 등은 Non-Project TEAL Activity로 별도 관리
// ★ SA가 추가 가능 (DB 테이블 기반)
}
```
**보완**: Overhead Type을 Enum 대신 **DB 테이블**로 관리 (SA 수정 가능 요건)
```sql
CREATE TABLE overhead_types (
id BIGINT IDENTITY PRIMARY KEY,
code VARCHAR(50) NOT NULL UNIQUE,
name VARCHAR(200) NOT NULL,
description NVARCHAR(500),
is_active BIT DEFAULT 1,
sort_order INT DEFAULT 0,
created_at DATETIME2 DEFAULT GETDATE()
);
-- 초기 데이터
INSERT INTO overhead_types (code, name, description) VALUES
('TRAINING', 'Training', 'Employee education and competency development'),
('SYS_PROC_DEV', 'System and Process Development', 'System and process development and improvement'),
('ORG_OPERATION', 'Organizational Operation', 'Internal organizational administrative tasks'),
('CORPORATE_INITIATIVE','Corporate Initiative or Strategy', 'Executive-led corporate strategic initiatives');
-- ★ 추가 유형은 SA가 화면에서 등록 (No.56: "향후 수정 가능")
```
**Non-Project TEAL**: Admin이 Non-Project 전용 TEAL을 설정 → 사용자는 이 TEAL에서만 Activity 선택 (No.57)
---
## 3. Canonical WBS 레벨 구조 상세 (No.33~34)
요구사항 No.34에서 명시된 정확한 구조:
```
Level 1: Project
Level 2: Phase (Engineering, Procurement, Construction, Commissioning, etc.)
Level 3: Asset or Area ★ 기존 계획 "Discipline/Category" → 수정
Level 4: Work or Discipline ★ 기존 계획 "Sub-Category/Work Package" → 수정
Level 5: Deliverable, Package, or Material ★ Engineering and SCM only (No.34)
```
> **주의**: Level 5는 Engineering/SCM Phase에서만 사용. Construction 등은 Level 4까지만.
### Project Type별 WBS 적용 (No.26)
| Project Type | WBS Level | 비고 |
|-------------|-----------|------|
| **EPC Project** | Level 2~5 | P6 WBS 연동, Canonical 매핑 |
| **Other Project** (Tender/Pre-FEED/FEED/IDD) | Level 2~4 | P6 연동 불필요, Canonical만 (No.62) |
| **Non-Project** (Overhead) | 없음 | WBS/Project 입력 불가 (No.59) |
```sql
-- Project Type Enum 보완
-- project_type: 'EPC', 'TENDER', 'PRE_FEED', 'FEED', 'INTERNAL_DESIGN', 'NON_PROJECT'
ALTER TABLE projects ADD COLUMN project_type VARCHAR(30) NOT NULL DEFAULT 'EPC';
-- Project Type별 WBS 레벨 제한
CREATE TABLE project_type_config (
id BIGINT IDENTITY PRIMARY KEY,
project_type VARCHAR(30) NOT NULL UNIQUE,
min_wbs_level INT DEFAULT 2,
max_wbs_level INT DEFAULT 5,
requires_p6 BIT DEFAULT 0,
requires_teal BIT DEFAULT 1,
description NVARCHAR(200)
);
INSERT INTO project_type_config VALUES
(1, 'EPC', 2, 5, 1, 1, 'EPC Project - P6 연동, Level 5까지'),
(2, 'TENDER', 2, 4, 0, 1, 'Tender/Bidding'),
(3, 'PRE_FEED', 2, 4, 0, 1, 'Pre-FEED'),
(4, 'FEED', 2, 4, 0, 1, 'FEED'),
(5, 'INTERNAL_DESIGN', 2, 4, 0, 1, 'Internal Design Development'),
(6, 'NON_PROJECT', 0, 0, 0, 0, 'Non-Project/Overhead');
```
---
## 4. 권한 매트릭스 (Sheet1 기반)
요구사항 원본 Sheet1의 기능별 역할 접근 권한:
| Category | Sub Category | SA(Admin) | PM | PL(LE)/GM/DL | Engineer/Staff |
|----------|-------------|-----------|-----|--------------|----------------|
| **Time Sheet** | Time Sheet Register | O | O | O | O |
| | Excel Import | O | O | O | - |
| **Project Mgmt** | Project Registration | O | O | - | - |
| | Project Information | O | - | - | - |
| **User Mgmt** | User Registration | O | O | O | - |
| | User Information | O | O | O | O |
| | ID/Password Mgmt | O | O | O | O |
| **WBS Mgmt** | WBS Upload | O | - | - | - |
| | WBS Version Mgmt | O | - | - | - |
| | TEAL Management | O | - | - | - |
| **Resource Assign** | Resource Availability | O | O | - | - |
| | Project Assign | O | - | - | - |
| | WBS Assign | O | O | - | - |
| | Task(TEAL) Assign | O | O | O | - |
| **My Project** | Assignment Status | O | O | O | O |
| | Favorite Setting | O | O | O | O |
| **Approval** | Approval Request | O | O | O | O |
| | Approval Management | O | O | O | - |
| | Approval History | O | O | O | O |
| **Report** | Project MH Analysis | O | O | O | - |
| | WBS MH Analysis | O | O | O | - |
| | Discipline MH Analysis | O | O | O | - |
| | Overhead MH Analysis | O | O | O | - |
| | WBS Change Review | O | O | O | - |
### Spring Security 보완
```java
// 역할 코드 보완: PL(LE)/GM = DL (Discipline Lead)
// 원본에서 Admin = SA, PL(LE)/GM = DL 매핑
// 권한 테이블 (DB 기반, SA가 수정 가능)
CREATE TABLE role_permissions (
id BIGINT IDENTITY PRIMARY KEY,
role_id BIGINT NOT NULL REFERENCES roles(id),
module VARCHAR(50) NOT NULL, -- TIMESHEET, PROJECT, USER, WBS, RESOURCE, APPROVAL, REPORT
sub_module VARCHAR(50) NOT NULL, -- REGISTER, IMPORT, UPLOAD, etc.
can_access BIT DEFAULT 0,
UNIQUE (role_id, module, sub_module)
);
// @PreAuthorize에서 DB 기반 권한 체크
@Component("perm")
public class PermissionChecker {
public boolean check(String module, String subModule) {
Long userId = SecurityUtils.getCurrentUserId();
return rolePermissionRepository.hasAccess(userId, module, subModule);
}
}
// Controller에서 사용
@GetMapping("/api/reports/project-hours")
@PreAuthorize("@perm.check('REPORT', 'PROJECT_MH_ANALYSIS')")
public ProjectHoursReport getProjectHours(...) { ... }
```
---
## 5. Resource Assignment 모듈 (누락 보완)
요구사항 No.42~50: 기존 계획서에 상세 누락된 모듈.
### 핵심 기능
| No. | 기능 | 설명 |
|-----|------|------|
| 42 | 기본 입력 기준 수정 | SA가 Timesheet 기본 설정 변경 가능 |
| 43 | 1일 최소 8시간 | 규칙 엔진 |
| 44 | Activity 최소 1개 | 빈 Timesheet 제출 불가 |
| 45 | 주 최대 52시간 | Location(국가)별 다르게 지정 가능 |
| 46 | 초과근무/휴게시간 규칙 | 규칙 지정 가능 |
| 47 | Project별 Assign | Discipline마다 0~N개 프로젝트 배정 |
| 48 | Non-Project 별도 Assign 불필요 | 모든 사용자 사용 가능 |
| 49 | Location/Job_Role 설정 | 프로젝트별 사용 가능한 Location, Role 설정 (PH2) |
| 50 | WBS Discipline 자동 Assign | PCM/PTK가 표준 템플릿으로 투입인력 일괄 등록 |
```sql
-- 근무 규칙 설정 (SA 관리, No.42~46)
CREATE TABLE work_rules (
id BIGINT IDENTITY PRIMARY KEY,
rule_name VARCHAR(100) NOT NULL,
location_code VARCHAR(50), -- 국가/지역별 규칙 (NULL=전체 기본값)
min_daily_hours DECIMAL(4,2) DEFAULT 8.00,
max_daily_hours DECIMAL(4,2) DEFAULT 10.00,
max_weekly_hours DECIMAL(5,2) DEFAULT 52.00,
overtime_threshold DECIMAL(4,2) DEFAULT 8.00, -- 초과근무 기준
break_time_minutes INT DEFAULT 60, -- 휴게시간
is_default BIT DEFAULT 0,
is_active BIT DEFAULT 1,
created_at DATETIME2 DEFAULT GETDATE()
);
INSERT INTO work_rules (rule_name, location_code, min_daily_hours, max_weekly_hours, is_default) VALUES
('Korea Standard', 'KR', 8.00, 52.00, 1),
('Offshore Standard', 'OFFSHORE', 8.00, 60.00, 0);
-- 프로젝트 인력 배정 (No.47~48)
CREATE TABLE project_assignments (
id BIGINT IDENTITY PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES projects(id),
user_id BIGINT NOT NULL REFERENCES users(id),
discipline VARCHAR(100),
assigned_by BIGINT REFERENCES users(id), -- PM/PCM/PTK
start_date DATE,
end_date DATE,
is_active BIT DEFAULT 1,
created_at DATETIME2 DEFAULT GETDATE(),
UNIQUE (project_id, user_id)
);
-- WBS별 Discipline 배정 (No.50)
CREATE TABLE wbs_discipline_assignments (
id BIGINT IDENTITY PRIMARY KEY,
canonical_wbs_id BIGINT NOT NULL REFERENCES canonical_wbs(id),
discipline VARCHAR(100) NOT NULL,
assigned_by BIGINT REFERENCES users(id),
created_at DATETIME2 DEFAULT GETDATE(),
UNIQUE (canonical_wbs_id, discipline)
);
```
### REST API 추가
```
# Resource Assignment (02-database-schema, 08-api-spec 보완)
GET /api/work-rules 근무 규칙 목록 (SA)
PUT /api/work-rules/{id} 근무 규칙 수정 (SA)
GET /api/projects/{id}/assignments 프로젝트 인력 배정 목록
POST /api/projects/{id}/assignments 인력 배정 (PM/PCM/PTK)
POST /api/projects/{id}/assignments/upload 인력 배정 일괄 업로드 (No.50)
DELETE /api/projects/{id}/assignments/{userId} 인력 배정 해제
GET /api/projects/{id}/wbs-disciplines WBS-Discipline 배정 현황
POST /api/projects/{id}/wbs-disciplines WBS-Discipline 배정
```
---
## 6. 비기능 요구사항 — 한화오션 표준 보안 SW 상세 (NF.3~10)
### 서버 보안 (NF.3)
| SW | 용도 | Azure 대응 |
|----|------|-----------|
| **HIWARE** | 서버 접근 제어 | Azure Bastion + HIWARE Agent |
| **V3** (AhnLab) | 서버 백신 | VM에 V3 Agent 설치 |
| **Secuver TOS** | 서버 보안 (파일 무결성 등) | VM에 Agent 설치 |
### DB 보안 (NF.4)
| SW | 용도 | Azure 대응 |
|----|------|-----------|
| **Cubeone** | DB 암호화 | Azure SQL TDE + Cubeone (컬럼 레벨) |
| **Dbsafer** | DB 접근 제어 | Dbsafer Proxy 구성 |
### 클라우드 보안 (NF.5)
| SW | 용도 |
|----|------|
| **Azure Defender** | 위협 탐지 |
| **Azure Log Analytics** | 보안 이벤트 분석 |
### 모니터링 (NF.8~10)
| SW | 용도 | 대상 |
|----|------|------|
| **onTune** | SMS (서버 모니터링) | VM CPU/Memory/Disk |
| **MCCS** | HA (Windows 클러스터) | WAS 이중화 (※ Linux → N/A) |
| **Maxguage** | DB 모니터링 | Azure SQL 성능 분석 |
| **Jennifer** | WAS 모니터링 | Spring Boot Tomcat APM |
### application-prod.yml 보완
```yaml
# Jennifer APM 연동 (NF.10)
# JVM Args: -javaagent:/opt/jennifer/agent.java/jennifer.jar
# Actuator + Prometheus (Maxguage 보완/대안)
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
health:
db:
enabled: true
redis:
enabled: true
```
### 보안성 심의 체크리스트 (NF.6~7)
```
□ 웹 애플리케이션 취약점 점검 (OWASP Top 10)
□ 모바일 앱 보안 점검 (해당 시 PH2)
□ 서버/네트워크 인프라 보안 점검
□ 소스코드 보안 점검 (SonarQube / Fortify)
□ 모의해킹 (Penetration Testing)
□ 개인정보 보호 관리 (개인정보보호법 준수)
□ 한화그룹 보안 표준 준수 확인
```
---
## 7. Timesheet 상세 보완
### Remark 필드 (No.67)
```
필수 입력 아님. 필요 시 아래 내용 입력:
- Change Order Number
- Deliverable Number
- 기타 참고 사항
```
**보완**: Change Order 관련 MH 관리를 위해 별도 Activity 분리 입력 방안 검토 필요
### Timesheet 행 구조 (No.69)
```
1행 = 1일자 × 1 Activity
------------------------------------------------------
번호 | 날짜 | WBS L1~5 | Activity | Manhour | Remark
------------------------------------------------------
1 | 4/7 | E.01.03 | Detail | 4.0 |
2 | 4/7 | E.01.04 | Review | 4.0 | ← 동일 날짜, 다른 Activity
------------------------------------------------------
일 합계: 8.0h
전체 합계: Summary Row 표시
```
### Excel Import 정확한 컬럼 (No.68)
```
표준 템플릿 컬럼:
| Date | Project Code | WBS L2 | WBS L3 | WBS L4 | WBS L5 | Activity | Hours | Remark |
```
---
## 8. 확인필요사항 (7건) 추적
원본 Excel 하단의 "확인필요사항" — 프로젝트 착수 전 고객 확정 필요.
| # | 영역 | 내용 | 현재 상태 | 계획 반영 |
|---|------|------|----------|----------|
| 1 | User Registration | 파트너사 및 외주 인력 관리 정책 — 파트너 마스터 연계 여부 | 별도 파트너 마스터 연계 미고려. 전사 데이터 표준화 후 검토 | PH1-1: 파일 업로드만 |
| 2 | User Home | 사용자 관리규정 및 권한관리 정책 — User Type별 업무범위 | No.18 참조 (기능 기반 역할 정의 확정) | plans/wbx-spring/02-auth-jwt-sso.md 반영 |
| 3 | WBS Upload | WBS별 Resource Plan 방식 — TT에서 투입시수 규모 세팅 여부 | TT에서 WBS별 투입시수 규모 세팅 | 05-wbs-teal.md 반영 |
| 4 | Resource Assignment | PM 인력 배치 시 해당 인력 스케줄 확인 및 참여 확인 절차 | PM/PCM/PTK가 WBS별 Discipline 선정 → 각 Discipline별 투입인력 선정 후 리스트 제출 | Resource Assignment 모듈 |
| 5 | Time Sheet (EPC) | C단계(Construction) 시수 입력 및 관리 방안 | **C단계 시수관리 대상 제외**. EPU 담당자의 C단계 관리업무만 TT에 등록 | 04-timesheet.md 주석 |
| 6 | Approval | 각 업무요건별 승인 절차 — 대상 Action 도출, 프로세스 설계 | User → DL → PM 3단계 확정 | 06-approval.md 반영 |
| 7 | Resource Assignment | Project Assignment 프로세스 상세 | SA가 Project 생성 → PM/PCM이 인력 배정 → 확정 | Resource Assignment 모듈 |
---
## 9. 외부 시스템 인터페이스 상세 (NF.13~15)
### 인터페이스 전체 맵
```
┌──────────────────┐ ┌─────────────┐ ┌────────────────┐
│ SAP │ │ │ │ │
│ SuccessFactors │────▶│ SAP BTP │────▶│ WTMgr │
│ (HR Master) │ │ (NF.13) │ │ Spring Boot │
└──────────────────┘ └─────────────┘ │ │
│ ┌──────────┐│
┌──────────────────┐ File Upload │ │ REST API ││
│ Primavera P6 │─────────────────────────▶│ │ ││
│ (WBS/Schedule) │ (NF.14, 물리적 I/F 없음) │ └──────────┘│
└──────────────────┘ │ │
│ ┌──────────┐│
┌──────────────────┐ Extractor │ │ Export ││
│ Cognite │◀────────────────────────│ │ API ││
│ (Data Platform) │ (NF.15) │ └──────────┘│
└──────────────────┘ └────────────────┘
```
### 9-1. SAP SuccessFactors 연동 (NF.13) — SAP BTP 필수
> **NF.13 원문**: "In the case of direct integration with SuccessFactors, SAP BTP must be applied."
#### 연동 아키텍처
```
SAP SuccessFactors
│ OData API (Employee Central)
┌─────────────────────────┐
│ SAP BTP │
│ (Business Technology │
│ Platform) │
│ │
│ ┌───────────────────┐ │
│ │ Integration Suite │ │
│ │ (CPI/CI) │ │
│ │ │ │
│ │ ● OData → REST │ │
│ │ ● 필드 매핑 │ │
│ │ ● 스케줄링 (배치) │ │
│ └───────┬───────────┘ │
└──────────┼──────────────┘
│ REST API (JSON)
┌─────────────────────────┐
│ WTMgr │
│ POST /api/integration │
│ /hr/sync │
└─────────────────────────┘
```
#### 단계별 구현
| Phase | 방식 | 설명 |
|-------|------|------|
| **PH1-1** | **파일 업로드** (No.1) | SA가 SF에서 Export한 Excel/CSV를 수동 업로드. BTP 불필요 |
| **PH1-2** | **배치 자동화** (No.3) | SAP BTP Integration Suite → 정기 Batch (일 1회) → WTMgr REST API |
| **PH2** | **실시간 이벤트** | SF Employee Events → BTP → WTMgr Webhook (입/퇴사 즉시 반영) |
#### SAP BTP Integration Suite 설정
```yaml
# BTP CPI iFlow 설정 예시
Source:
System: SAP SuccessFactors
API: /odata/v2/PerPersonal, /odata/v2/EmpJob, /odata/v2/FODepartment
Auth: OAuth2 (SAP Trust)
Mapping:
SF.personIdExternal → WTMgr.employeeNumber
SF.firstName + lastName → WTMgr.fullName
SF.email → WTMgr.email
SF.businessUnit → WTMgr.businessUnit (LV1)
SF.division → WTMgr.division (LV2)
SF.department → WTMgr.department (LV3)
SF.customString1 → WTMgr.disciplineTeam (LV4) # Discipline/Team
SF.customString2 → WTMgr.part (LV5) # Part
SF.attendanceType → WTMgr.attendanceType
SF.jobCode → WTMgr.individualJobCode
Target:
System: WTMgr
Endpoint: POST /api/integration/hr/sync
Auth: Service Account JWT (M2M)
Schedule: Daily 02:00 KST
```
#### Spring Boot 수신 API
```java
@RestController
@RequestMapping("/api/integration/hr")
@PreAuthorize("hasRole('SYSTEM') or hasRole('SA')") // M2M 또는 SA만
public class HrIntegrationController {
private final HrSyncService hrSyncService;
/**
* SAP BTP → WTMgr HR 데이터 동기화
* PH1-1: SA 수동 파일 업로드 대안
* PH1-2: BTP CPI 자동 호출
*/
@PostMapping("/sync")
public HrSyncResult syncEmployees(@Valid @RequestBody HrSyncRequest request) {
return hrSyncService.syncAll(request.getEmployees());
}
/**
* SA 수동 업로드 (PH1-1: BTP 없이 Excel 업로드)
*/
@PostMapping("/upload")
public HrSyncResult uploadExcel(@RequestParam("file") MultipartFile file) {
return hrSyncService.uploadFromExcel(file);
}
}
// 동기화 요청 DTO
public record HrSyncRequest(
List<HrEmployeeDto> employees,
String syncSource, // "SAP_BTP" | "MANUAL_UPLOAD"
LocalDateTime syncTime
) {}
public record HrEmployeeDto(
String employeeNumber,
String fullName,
String email,
String businessUnit, // LV1
String division, // LV2
String department, // LV3
String disciplineTeam, // LV4
String part, // LV5
String attendanceType,
String individualJobCode,
String jobRole,
LocalDate startDate,
LocalDate endDate,
boolean isActive
) {}
```
#### SAP BTP 사전 확보 사항
| 항목 | 제공 주체 | 마감 |
|------|----------|------|
| BTP 테넌트 접근 권한 | 한화시스템/SAP | W2 |
| SF OData API 엔드포인트 및 인증 정보 | 한화시스템 | W2 |
| 필드 매핑 확정 (SF → WTMgr) | 한화오션 + 아큐라 | W3 |
| BTP CPI iFlow 개발/배포 권한 | 한화시스템 | PH1-2 |
### 9-2. P6 연동 (NF.14) — 파일 기반만
> **NF.14 원문**: "Since there is no physical interface with P6, data integration must be implemented using exported files."
| 항목 | 내용 |
|------|------|
| 연동 방식 | P6 Export → Excel/CSV → WTMgr Upload |
| 물리적 I/F | **없음** (API 연동 불가) |
| 업로드 주체 | **PM** (No.27), PCM이 승인 (No.35) |
| 필수 필드 | WBS Level 1~5, P6 Activity ID, P6 Activity Name, Version Number, Effective Date, Approval Reference (No.31) |
| 빈도 | WBS 변경 시 수시 + 월 1회 Snapshot 비교 (No.32) |
### 9-3. Cognite 연동 (NF.15) — PH2
> **NF.15 원문**: "An extractor server is required to support interface integration with Cognite."
```
Export 대상 Dimension/Fact (No.80):
- Employee Dimension (사번, 이름, 부서, Discipline)
- Project Dimension (프로젝트코드, 이름, Type)
- Canonical WBS Dimension (WBS 코드, Level, 이름)
- Time Fact Table (날짜, 시수, Activity, 승인상태)
- Mapping Version Metadata (★ 기존 계획 누락 → 추가)
```
```java
// Cognite Export REST API (PH2)
@GetMapping("/api/integration/cognite/export")
@PreAuthorize("hasRole('SA')")
public CogniteExportData exportForCognite(
@RequestParam @DateTimeFormat(iso = DATE) LocalDate from,
@RequestParam @DateTimeFormat(iso = DATE) LocalDate to) {
return CogniteExportData.builder()
.employees(employeeDimensionService.export())
.projects(projectDimensionService.export())
.canonicalWbs(wbsDimensionService.export())
.timeFacts(timesheetFactService.export(from, to))
.mappingVersions(wbsVersionService.exportMetadata()) // ★ 추가
.exportedAt(LocalDateTime.now())
.build();
}
```
---
## 10. 최종 점검 — 기존 계획서 오류 정정
### 정정 사항 요약
| # | 기존 계획서 | 수정 내용 | 근거 |
|---|-----------|----------|------|
| 1 | 조직 4레벨 (BU/Division/Dept/Section) | **5레벨**: BU/Division/Dept/Discipline·Team/**Part** + Attendance Type, Individual Job Code | No.2 (Eng) |
| 2 | Canonical WBS L3 = "Discipline/Category" | **L3 = Asset or Area** | No.34 (Eng) |
| 3 | Canonical WBS L4 = "Sub-Category/Work Package" | **L4 = Work or Discipline** | No.34 (Eng) |
| 4 | Canonical WBS L5 = "Deliverable/Activity" | **L5 = Deliverable, Package, or Material (Engineering & SCM only)** | No.34 (Eng) |
| 5 | Overhead 9종 (Leave, Sick Leave 등 포함) | **4종**: Training, Sys&Proc Dev, Org Operation, Corporate Initiative | No.56 (Eng) |
| 6 | WBS 업로드 주체 = PCM/PTK | **PM**이 업로드, **PCM**이 승인 | No.27, No.35 |
| 7 | No.49 Location/Role = PH2 | Phase 미지정 (메인 요구사항), 설계 시 고려 필요 | No.49 |
| 8 | EPC 추가 필드 미반영 | Location, Role/Position, **Earned Value(진행률)** 검토 | No.65 |
| 9 | Cognite Export 4개 Dimension | **5개**: + Mapping Version Metadata | No.80 (Eng) |
| 10 | 미완료 Timesheet 알림 미반영 | **필수**: 담당자에게 미완료 Timesheet alert 전송 | No.70 |
| 11 | Project 생성 = PM 직접 | PM/PCM 정보 입력 → **SA 승인** 후 등록 | No.25 |
| 12 | Non-Project TEAL = 기본 내장 | **Admin이 설정**한 Non-Project TEAL에서만 Activity 선택 | No.57 |
| 13 | SAP BTP 연동 = 간략 설명만 | **상세 아키텍처 추가** (BTP CPI iFlow, OData → REST 매핑) | NF.13 |
### 04-timesheet-module.md 보완 필요
```java
// No.65: EPC Timesheet 추가 필드 (PH2 후보, 설계 시 확장 고려)
@Entity @Table(name = "timesheet_entries")
public class TimesheetEntry extends BaseEntity {
// ... 기존 필드 ...
// ★ No.65 추가 필드 (nullable, PH2에서 활성화)
private String location; // Onshore/Offshore/국가코드
private String rolePosition; // Job Role (동일 사용자 복수 Role 가능)
private BigDecimal earnedValue; // 진행률 (%) — Earned Value
}
// ★ 주의: "동일 사용자가 복수 Role → Unit Rate 변경", "Location 변경 → Unit Rate 변경" (No.65 Remark)
```
### 06-approval-workflow.md 보완 필요
```java
// No.70: 미완료 Timesheet 알림 (★ 기존 계획 누락)
@Component
public class TimesheetReminderScheduler {
/**
* 매일 오후 5시: 당일 미작성 Timesheet 알림 (No.70)
* "The system must send alerts to responsible users
* for incomplete timesheets to ensure timely submission"
*/
@Scheduled(cron = "0 0 17 * * MON-FRI")
public void sendDailyReminder() {
List<User> usersWithoutEntry = timesheetService
.findUsersWithoutEntryForDate(LocalDate.now());
for (User user : usersWithoutEntry) {
notificationService.sendTimesheetReminder(user, LocalDate.now());
}
}
/**
* 매주 금요일 오전 10시: 주간 미제출 Timesheet 알림
*/
@Scheduled(cron = "0 0 10 * * FRI")
public void sendWeeklySubmitReminder() {
LocalDate weekStart = LocalDate.now().with(DayOfWeek.MONDAY);
List<User> unsubmitted = timesheetService
.findUsersWithUnsubmittedWeek(weekStart);
for (User user : unsubmitted) {
notificationService.sendWeeklySubmitReminder(user, weekStart);
}
}
}
```
### 05-wbs-teal-module.md 보완 필요
```java
// No.27: WBS 업로드 주체 수정
// 기존: PCM/PTK 업로드
// 수정: PM이 업로드 → PCM이 승인 (No.35)
@PostMapping("/api/projects/{projectId}/wbs/upload")
@PreAuthorize("hasAnyRole('SA', 'PM')") // ★ PM 권한 (기존 PCM → PM)
public WbsVersionDto uploadP6Wbs(...) { ... }
@PostMapping("/api/projects/{projectId}/wbs/versions/{verId}/approve")
@PreAuthorize("hasAnyRole('SA', 'PCM')") // ★ PCM 승인
public WbsVersionDto approveWbs(...) { ... }
```
---
## 11. API 스펙 보완 (07-api-spec.md 추가분)
### 추가 필요 API (기존 57개 → 최종 78개)
| Method | Path | 설명 | Phase |
|--------|------|------|-------|
| GET | `/api/overhead-types` | Overhead Type 목록 | PH1-1 |
| POST | `/api/overhead-types` | Overhead Type 추가 (SA) | PH1-1 |
| PUT | `/api/overhead-types/{id}` | Overhead Type 수정 (SA) | PH1-1 |
| GET | `/api/work-rules` | 근무 규칙 목록 | PH1-1 |
| PUT | `/api/work-rules/{id}` | 근무 규칙 수정 (SA) | PH1-1 |
| GET | `/api/projects/{id}/assignments` | 프로젝트 인력 배정 목록 | PH1-1 |
| POST | `/api/projects/{id}/assignments` | 인력 배정 | PH1-1 |
| POST | `/api/projects/{id}/assignments/upload` | 인력 일괄 업로드 | PH1-1 |
| DELETE | `/api/projects/{id}/assignments/{userId}` | 인력 배정 해제 | PH1-1 |
| GET | `/api/projects/{id}/wbs-disciplines` | WBS-Discipline 현황 | PH1-1 |
| POST | `/api/projects/{id}/wbs-disciplines` | WBS-Discipline 배정 | PH1-1 |
| POST | `/api/projects/{id}/wbs/versions/{id}/approve` | WBS 버전 승인 (PCM) ★ 추가 | PH1-1 |
| GET | `/api/role-permissions` | 역할별 권한 매트릭스 (SA) | PH1-1 |
| POST | `/api/integration/hr/sync` | SAP BTP HR 동기화 수신 ★ 추가 | PH1-2 |
| POST | `/api/integration/hr/upload` | SA 수동 HR 파일 업로드 ★ 추가 | PH1-1 |
| GET | `/api/notifications/pending` | 미완료 Timesheet 알림 목록 ★ 추가 | PH1-1 |
| GET | `/api/users/me/favorites` | 내 Favorite 설정 | PH2 |
| PUT | `/api/users/me/favorites` | Favorite 저장 | PH2 |
| GET | `/api/integration/cognite/export` | Cognite Export ★ 추가 | PH2 |
| GET | `/api/reports/wbs-misalign` | WBS Mis-Align 검토 (No.81) ★ 추가 | PH2 |
| GET | `/api/reports/discipline-productivity` | Discipline 생산성 (No.84) ★ 추가 | PH2 |
### 최종 API 수
| 모듈 | PH1-1차 | PH1-2차 | PH2 | 합계 |
|------|---------|---------|-----|------|
| Auth | 8 | 0 | 0 | 8 |
| Users | 7 | 1 | 2 | 10 |
| Projects | 7 | 0 | 0 | 7 |
| WBS | 6 | 1 | 0 | 7 |
| TEAL | 4 | 0 | 0 | 4 |
| Timesheets | 8 | 0 | 0 | 8 |
| Approvals | 7 | 1 | 0 | 8 |
| Reports | 4 | 2 | 3 | 9 |
| Home/Notification | 3 | 0 | 0 | 3 |
| Resource Assign | 8 | 0 | 0 | 8 |
| Config (규칙/Type) | 4 | 0 | 0 | 4 |
| **Integration (SAP/Cognite)** | **1** | **1** | **1** | **3** |
| **합계** | **67** | **6** | **6** | **79** |