Files
sam-docs/dev/dev_plans/integrated-test-scenarios.md
권혁성 db63fcff85 refactor: [docs] 팀별 폴더 구조 재편 (공유/개발/프론트/기획)
- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동)
- 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/)
- 기획팀 폴더 requests/ 생성
- plans/ → dev/dev_plans/ 이름 변경
- README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용)
- resources.md 신규 (노션 링크용, assets/brochure 이관 예정)
- CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동
- 전체 참조 경로 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:46:03 +09:00

20 KiB

통합 개선 계획 — 기능 단위 테스트 시나리오

통합 계획: integrated-master-plan.md 목적: 각 작업 완료 후 즉시 검증할 수 있는 기능 단위(FU) 테스트 시나리오 작성일: 2026-02-27


테스트 환경

항목
프론트 dev.sam.kr (Next.js)
API api.sam.kr (Laravel)
관리자 mng.sam.kr / admin.sam.kr
DB Docker sam-mysql-1

FU-1: 수주 → 작업지시 생성 시 product_code 전달

작업: OrderService::createProductionOrder options 복사에 product_code 추가 Phase: 1 (작업 1.1) 수정 파일: api/app/Services/OrderService.php (L1410)

선행 조건

  • product_code가 있는 수주 데이터 1건 이상 존재
  • 해당 수주의 order_nodes.options.product_code에 값이 있어야 함

테스트 순서

# 화면 조작 기대 결과
1 수주관리 (/sales/order-management-sales) product_code가 있는 수주 1건 클릭 → 상세 페이지 진입 수주 상세 정상 표시
2 수주 상세 "작업지시 생성" 버튼 클릭 작업지시 생성 성공 메시지
3 작업지시 관리 (/production/work-orders) 방금 생성한 작업지시 찾기 → 행 클릭 상세 정보 표시

기대 결과 — DB 확인

-- 방금 생성한 작업지시의 품목에서 product_code 확인
SELECT woi.id,
       JSON_EXTRACT(woi.options, '$.product_code') as product_code,
       JSON_EXTRACT(woi.options, '$.product_name') as product_name
FROM work_order_items woi
JOIN work_orders wo ON woi.work_order_id = wo.id
WHERE wo.id = {새로_생성된_작업지시_ID}
  AND woi.deleted_at IS NULL;

정상: product_code에 값이 있음 (예: FG-KQTS01-측면형-SUS) 비정상: product_code가 NULL

엣지 케이스

케이스 조작 기대 결과
product_code가 없는 수주 해당 수주로 작업지시 생성 오류 없이 생성, product_code는 NULL
product_code가 빈 문자열("") 해당 수주로 작업지시 생성 product_code가 options에 포함되지 않음 (empty 필터링)

FU-2: 작업지시 관리에서 수주 연동 등록 시 product_code 전달

작업: WorkOrderService::store 수주복사 로직에 product_code 추가 Phase: 1 (작업 1.2) 수정 파일: api/app/Services/WorkOrderService.php (L287-296)

선행 조건

  • FU-1과 동일 (product_code 있는 수주)

테스트 순서

# 화면 조작 기대 결과
1 작업지시 관리 (/production/work-orders) 우측 상단 "등록" 또는 ?mode=new 등록 폼 표시
2 등록 폼 "수주 연동 등록" 라디오 선택 수주 선택 모달 활성화
3 수주 선택 모달 product_code가 있는 수주 선택 기본 정보 자동 채움
4 등록 폼 공정 선택 → 출고예정일 입력 → "등록" 버튼 작업지시 생성 성공

기대 결과 — DB 확인

-- FU-1과 동일 쿼리, 새 작업지시 ID로 실행
SELECT woi.id,
       JSON_EXTRACT(woi.options, '$.product_code') as product_code,
       JSON_EXTRACT(woi.options, '$.product_name') as product_name
FROM work_order_items woi
WHERE woi.work_order_id = {새_작업지시_ID}
  AND woi.deleted_at IS NULL;

정상: product_code 값 존재 FU-1과 차이: 이 경로는 WorkOrderService::store를 통과 (OrderService 아님)


FU-3: 작업지시 품목 수정 시 product_code 보존

작업: WorkOrderService::update 품목 수정 시 기존 options 보존 확인 Phase: 1 (작업 1.4) 수정 파일: api/app/Services/WorkOrderService.php (L416-438)

선행 조건

  • FU-1 또는 FU-2로 생성된 작업지시 (product_code 있는 것)

테스트 순서

# 화면 조작 기대 결과
1 작업지시 상세 product_code가 있는 작업지시 진입 상세 정보 표시
2 상세 → 수정 품목명 또는 수량 변경 → 저장 수정 성공

기대 결과 — DB 확인

-- 수정 후 product_code가 사라지지 않았는지 확인
SELECT woi.id,
       JSON_EXTRACT(woi.options, '$.product_code') as product_code,
       JSON_EXTRACT(woi.options, '$.floor') as floor,
       JSON_EXTRACT(woi.options, '$.width') as width
FROM work_order_items woi
WHERE woi.work_order_id = {수정한_작업지시_ID}
  AND woi.deleted_at IS NULL;

정상: product_code, floor, width 등 기존 options 값이 모두 유지 비정상: product_code가 NULL로 변경됨 (덮어쓰기 발생)


FU-4: 기존 데이터 보정 마이그레이션

작업: 기존 work_order_items에 product_code 역추적 보정 Phase: 1 (작업 1.5) 실행: 마이그레이션 (스냅샷 백업 후)

선행 조건

  • FU-1, FU-2 백엔드 수정 배포 완료
  • Phase 0 사전 조사로 영향 범위 파악 완료

테스트 순서

# 조작 기대 결과
1 마이그레이션 실행 전 — 백업 테이블 존재 확인 work_order_items_backup_product_code 생성됨
2 마이그레이션 실행 로그에 product_code 보정 완료: N/M (X%) 출력
3 보정 결과 확인 아래 SQL로 확인

기대 결과 — DB 확인

-- 보정 후 전체 현황
SELECT COUNT(*) as total,
       COUNT(CASE WHEN JSON_EXTRACT(options, '$.product_code') IS NOT NULL THEN 1 END) as with_code,
       ROUND(COUNT(CASE WHEN JSON_EXTRACT(options, '$.product_code') IS NOT NULL THEN 1 END) * 100.0 / COUNT(*), 1) as pct
FROM work_order_items WHERE deleted_at IS NULL;

-- 보정 정확도 (원본 대조)
SELECT COUNT(*) as total_checked,
       SUM(CASE WHEN JSON_EXTRACT(woi.options, '$.product_code') = JSON_EXTRACT(onode.options, '$.product_code')
            THEN 1 ELSE 0 END) as match_count
FROM work_order_items woi
JOIN order_items oi ON woi.source_order_item_id = oi.id
JOIN order_nodes onode ON oi.order_node_id = onode.id
WHERE woi.deleted_at IS NULL
  AND JSON_EXTRACT(woi.options, '$.product_code') IS NOT NULL;

정상: 보정율 90% 이상, 정확도 MATCH 100% 비정상: 보정율 50% 미만 → Phase 0 데이터 재확인 필요


FU-5: WorkerScreen에 제품코드 표시

작업: WorkerScreen actions.ts + index.tsx에 productCode 매핑/표시 Phase: 1 (작업 1.6) 수정 파일: react/src/components/production/WorkerScreen/actions.ts, index.tsx

선행 조건

  • FU-1 또는 FU-2 완료 (product_code가 있는 작업지시 존재)
  • 또는 FU-4 완료 (기존 데이터 보정됨)

테스트 순서

# 화면 조작 기대 결과
1 작업자 화면 (/production/worker-screen) 접속 공정 탭(스크린/슬랫/절곡) + 작업 카드 표시
2 작업 카드 product_code가 있는 작업지시의 카드 확인 제품코드가 카드에 표시됨
3 작업 카드 product_code가 없는 작업지시의 카드 확인 기존처럼 품목명만 표시 (오류 없음)

기대 화면

product_code 있는 경우:

┌──────────────────────────────────┐
│ FG-KQTS01-측면형-SUS - 슬랫 방화  │  ← "제품코드 - 품목명" 형태
│ FSS-01 | 3층                      │
│ [작업시작] [검사] [자재투입]       │
└──────────────────────────────────┘

product_code 없는 경우:

┌──────────────────────────────────┐
│ 슬랫 방화                         │  ← 품목명만 (기존과 동일)
│ FSS-01 | 3층                      │
│ [작업시작] [검사] [자재투입]       │
└──────────────────────────────────┘

FU-6: ProductionDashboard에 제품코드 표시

작업: ProductionDashboard actions.ts에 productCode 매핑 Phase: 1 (작업 1.7) 수정 파일: react/src/components/production/ProductionDashboard/actions.ts

선행 조건

  • FU-5와 동일

테스트 순서

# 화면 조작 기대 결과
1 생산 현황판 (/production/dashboard) 접속 공정 탭 + 통계 + 카드 표시
2 긴급/지연/최근완료 카드 product_code 있는 작업지시 확인 제품코드 표시

기대 화면

FU-5와 동일한 패턴. 카드에 제품코드 - 품목명 형태로 표시.


FU-7: 견적 저장 시 quotes.product_code 저장

작업: QuoteService에서 견적 저장 시 quotes.product_code 컬럼에 대표 코드 저장 Phase: 2B (작업 2B.1) 수정 파일: api/app/Services/Quote/QuoteService.php

선행 조건

  • Phase 1 완료

테스트 순서

# 화면 조작 기대 결과
1 견적 관리 (/sales/quote-management) "신규 견적" 버튼 견적 등록 폼
2 견적 등록 제품코드가 포함된 견적 데이터 입력 → 저장 저장 성공

기대 결과 — DB 확인

-- 방금 저장한 견적의 product_code 확인
SELECT id, product_code, product_name,
       JSON_EXTRACT(calculation_inputs, '$.items[0].productCode') as first_item_code
FROM quotes
WHERE id = {새_견적_ID};

정상: product_code = 첫 번째 개소의 productCode 값 다중 개소: 첫 번째 개소 코드가 대표값으로 저장됨

엣지 케이스

케이스 기대 결과
개소 1개 견적 product_code = 해당 개소 코드
개소 3개 견적 product_code = 첫 번째 개소 코드
productCode 없는 견적 product_code = NULL (오류 없음)

FU-8: 품질검사 ↔ 작업지시 FK 연결

작업: inspections 테이블에 work_order_id FK 추가 + 보정 Phase: 2B (작업 2B.4~2B.7) 수정 파일: 마이그레이션 + api/app/Services/InspectionService.php

선행 조건

  • Phase 1 완료
  • Phase 0에서 lot_no 중복 건수 파악 완료

테스트 — 마이그레이션

-- FK 컬럼 추가 확인
SHOW COLUMNS FROM inspections LIKE 'work_order_id';
-- 결과: work_order_id | int | YES | NULL

-- 기존 inspections 정상 조회 (회귀 테스트)
SELECT COUNT(*) FROM inspections WHERE deleted_at IS NULL;

테스트 — 신규 검사 생성

# 화면 조작 기대 결과
1 작업자 화면 작업 카드 → "중간검사" 버튼 InspectionInputModal 열림
2 검사 입력 모달 검사 데이터 입력 → 저장 저장 성공
-- 새로 생성된 inspection에 work_order_id가 있는지 확인
SELECT id, work_order_id, lot_no
FROM inspections
ORDER BY id DESC LIMIT 5;

정상: work_order_id 값 존재 (해당 작업지시 ID) 비정상: work_order_id NULL

테스트 — 기존 데이터 보정

-- lot_no 기반 역추적 보정 결과
SELECT COUNT(*) as total,
       COUNT(work_order_id) as with_wo_id,
       ROUND(COUNT(work_order_id) * 100.0 / COUNT(*), 1) as pct
FROM inspections WHERE deleted_at IS NULL;

정상: 보정율 95% 이상


FU-9: inspection-config API 동작 확인

작업: GET /api/v1/work-orders/{id}/inspection-config 구현 Phase: 3 (작업 3.1) 수정 파일: API Controller + Route

선행 조건

  • Phase 1 완료 (product_code 전달)
  • Phase 2A 완료 (API 설계)

테스트 — API 직접 호출

# 절곡 공정 작업지시
curl -s "https://api.sam.kr/api/v1/work-orders/{절곡_작업지시_ID}/inspection-config" \
  -H "Authorization: Bearer {token}" | jq .

기대 응답 — 절곡 공정

{
  "success": true,
  "data": {
    "work_order_id": 123,
    "process_type": "bending",
    "product_code": "KWE01",
    "template_id": 45,
    "items": [
      {
        "id": "guide-rail-wall",
        "category": "KWE01",
        "product_name": "가이드레일",
        "product_type": "벽면형",
        "gap_points": [...]
      }
    ]
  }
}

기대 응답 — 스크린/슬랫 공정

{
  "success": true,
  "data": {
    "work_order_id": 456,
    "process_type": "screen",
    "product_code": "FG-KQTS01",
    "template_id": 12,
    "items": []
  }
}

엣지 케이스

케이스 API 호출 기대 응답
절곡 + KWE01 work_order_id=절곡KWE01 items에 KWE01 구성품 목록
절곡 + KSS01 work_order_id=절곡KSS01 items에 KSS01 전용 구성품 (KWE01과 다름)
스크린 공정 work_order_id=스크린 process_type="screen", items=[]
product_code 없는 작업지시 work_order_id=수동생성 product_code=null, items=[]
존재하지 않는 ID work_order_id=999999 404 에러
응답 시간 모든 케이스 < 200ms

FU-10: 절곡 검사 성적서 동적 구성품 표시

작업: TemplateInspectionContent에서 API 기반 구성품 로딩 Phase: 3 (작업 3.2) 수정 파일: react/.../documents/TemplateInspectionContent.tsx

선행 조건

  • FU-9 완료 (inspection-config API 동작)

테스트 순서 — KWE01 제품

# 화면 조작 기대 결과
1 작업자 화면 절곡 탭 선택 → KWE01 작업 카드 클릭 작업 상세
2 작업 상세 "중간검사" 버튼 검사 모달 열림
3 검사 모달 검사 성적서 탭 (또는 TemplateInspectionContent 영역) 동적 구성품 목록 표시

기대 화면 — KWE01

┌─────────────────────────────────────────────────────┐
│ 절곡 중간검사 성적서                                    │
├─────────────────────────────────────────────────────┤
│                                                     │
│  ▼ 개소 1 (1층 FSS-01)                               │
│  ┌─────────────┬──────┬────────┬─────────────────┐  │
│  │ 구성품       │ OK/NG│ 길이   │ 간격 포인트       │  │
│  ├─────────────┼──────┼────────┼─────────────────┤  │
│  │ 가이드레일벽면│  ○   │ [    ] │ ① ② ③ ④ ⑤     │  │
│  │ 가이드레일측면│  ○   │ [    ] │ ① ② ③ ④ ⑤     │  │
│  │ 케이스       │  ○   │ [    ] │ ① ② ③ ④        │  │
│  │ 하단마감재    │  ○   │ [    ] │ ① ②            │  │
│  │ 하단L-BAR    │  ○   │ [    ] │ ①              │  │
│  │ 연기차단재W50 │  ○   │ [    ] │ ① ②            │  │
│  │ 연기차단재W80 │  ○   │ [    ] │ ① ②            │  │
│  └─────────────┴──────┴────────┴─────────────────┘  │
│                                                     │
│  ▼ 개소 2 (2층 FSS-02)                               │
│  (동일 구조)                                          │
└─────────────────────────────────────────────────────┘

테스트 순서 — KSS01 제품 (다른 구성품)

# 화면 조작 기대 결과
1 작업자 화면 KSS01 절곡 작업 카드 → 중간검사 검사 모달
2 검사 성적서 구성품 목록 확인 KWE01과 다른 구성품 표시

정상: KSS01 전용 구성품이 표시됨 (KWE01의 7개와 다른 항목) 비정상: KWE01과 동일한 7개 항목 표시 (하드코딩 그대로)

테스트 — 저장/복원 사이클

# 조작 기대 결과
1 검사 데이터 입력 (OK/NG, 측정값, 간격) 입력값 반영
2 저장 버튼 저장 성공 메시지
3 검사 모달 닫기 → 다시 열기 입력했던 데이터 그대로 복원
4 다른 개소 선택 해당 개소 데이터 표시 (개소 간 데이터 독립)

테스트 — Fallback

케이스 조작 기대 결과
API 응답 items=[] (BOM 미등록) 해당 작업지시 검사 열기 DEFAULT_GAP_PROFILES 기본값 사용, 기존과 동일 표시
API 타임아웃 (네트워크 지연 시뮬레이션) buildBendingProducts() fallback 동작, 에러 없음

FU-11: createInspectionDocument 트랜잭션 보강

작업: lockForUpdate + DB::transaction 추가 Phase: 3 (작업 3.5) 수정 파일: api/app/Services/WorkOrderService.php

선행 조건

  • FU-10 완료

테스트 순서

# 조작 기대 결과
1 작업자 화면 → 중간검사 → 검사 문서 생성 정상 생성
2 같은 작업지시에 대해 다시 검사 문서 생성 시도 기존 문서 반환 (중복 생성 안 됨)

DB 확인

-- 동일 작업지시에 검사 문서가 1개만 있는지 확인
SELECT linkable_id, template_id, COUNT(*) as cnt
FROM documents
WHERE linkable_type = 'App\\Models\\Production\\WorkOrder'
  AND deleted_at IS NULL
GROUP BY linkable_id, template_id
HAVING COUNT(*) > 1;

정상: 결과 0건 (중복 없음) 비정상: 결과 있음 (중복 문서 존재)


기능별 스크린/슬랫 회귀 테스트

대상: 모든 FU 완료 후 목적: 기존 스크린/슬랫 검사가 영향받지 않았는지 확인

# 화면 조작 기대 결과
1 작업자 화면 → 스크린 탭 스크린 작업 카드 → 중간검사 기존과 동일하게 검사 입력 가능
2 스크린 검사 데이터 입력 → 저장 → 재조회 저장/복원 정상
3 작업자 화면 → 슬랫 탭 슬랫 작업 카드 → 중간검사 기존과 동일
4 슬랫 검사 데이터 입력 → 저장 → 재조회 저장/복원 정상
5 작업지시 목록 API /api/v1/work-orders 호출 정상 응답, 에러 0건
6 작업지시 상세 API /api/v1/work-orders/{id} 호출 정상 응답

FU 실행 순서 체크리스트

Phase 0: 사전 조사 (SQL만, FU 없음)
    ↓
Phase 1:
    □ FU-1: 수주→작업지시 product_code 전달 (OrderService)
    □ FU-2: 작업지시 수주연동 등록 product_code (WorkOrderService.store)
    □ FU-3: 작업지시 수정 시 options 보존 (WorkOrderService.update)
    □ FU-4: 기존 데이터 보정 마이그레이션
    □ FU-5: WorkerScreen 제품코드 표시
    □ FU-6: ProductionDashboard 제품코드 표시
    □ 회귀: 스크린/슬랫 검사 정상 동작 확인
    ↓
Phase 2A: 분석/설계 (FU 없음, 문서 산출물)
Phase 2B:
    □ FU-7: 견적 저장 시 product_code 저장
    □ FU-8: 품질검사 work_order_id FK 연결
    ↓
Phase 3:
    □ FU-9: inspection-config API 동작
    □ FU-10: 절곡 검사 성적서 동적 구성품
    □ FU-11: 트랜잭션 보강 (중복 생성 방지)
    □ 회귀: 스크린/슬랫 + 기존 절곡(레거시) 정상

변경 이력

날짜 항목 변경 내용
2026-02-27 문서 작성 11개 FU 테스트 시나리오 + 회귀 테스트 작성

이 문서는 integrated-master-plan.md의 기능 단위 테스트 시나리오입니다.