Files
sam-docs/dev/dev_plans/bom-item-mapping-plan.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

14 KiB

BOM 아이템 ↔ Items Master 매핑 작업 계획

작성일: 2026-02-05 목적: BOM 산출 로직에서 생성하는 모든 아이템에 SAM items master의 item_code/item_id를 매핑하여, 수주 등록 시 코드 기반 아이템 관리가 가능하도록 함 상태: Phase 1, 2 완료 (검증 대기)


📍 현재 진행 상태

항목 내용
마지막 완료 작업 Phase 2: BOM 산출 로직 매핑 수정 완료
다음 작업 Phase 3: 수주 등록 화면에서 검증
진행률 2/3 Phase (66%)
마지막 업데이트 2026-02-05

1. 개요

1.1 문제 상황

현재 상태:
- KyungdongFormulaHandler에서 22종 아이템 생성
- 그 중 5종은 item_code/item_id 없이 이름만으로 생성됨:
  1. 케이스 마구리 (calculateSteelItems)
  2. L바 (calculateSteelItems)
  3. 무게평철12T (calculateSteelItems)
  4. 검사비 (calculateDynamicItems) ← 유일한 SAM 미등록 아이템
  5. 주자재(스크린/슬랫) (calculateDynamicItems) ← KD-* 코드 사용

문제점:
- 수주 등록 시 아이템 그룹핑/집계에서 코드 기반 매칭 불가
- item_code가 없으면 item_name으로만 집계되어 중복 발생

1.2 목표 상태

목표:
- BOM 산출 결과의 모든 22종 아이템에 item_code + item_id 필수
- 수주 등록 시 동일 item_code 기준으로 수량/금액 집계

기대 효과:
- 3개소에 "환봉" 각 1개씩 → item_code "90201" 기준 3개로 집계

1.3 핵심 원칙

┌─────────────────────────────────────────────────────────────────┐
│  🎯 핵심 원칙 (CRITICAL)                                         │
├─────────────────────────────────────────────────────────────────┤
│  1. items master에 등록된 제품을 매핑해야 함                       │
│     → 코드를 임의로 만들어내면 안됨                                │
│  2. 기존 EST-/BD-/PT- 코드 체계를 활용                            │
│  3. BOM 산출 결과의 모든 아이템에 item_code + item_id 필수          │
└─────────────────────────────────────────────────────────────────┘

1.4 변경 승인 정책

분류 예시 승인
즉시 가능 BOM 로직 내 item_code/item_id 매핑 추가 불필요
⚠️ 컨펌 필요 items master에 신규 아이템 등록 필수
🔴 금지 items 테이블 구조 변경, 기존 코드 체계 변경 별도 협의

2. 전체 아이템 매핑 테이블 (22종)

2.1 calculateSteelItems (절곡품) - 10종

# BOM 아이템명 현재 item_code SAM 매핑 코드 SAM item_id 매핑 방법
1 케이스 null BD-케이스-{규격} lookup 규격으로 items 검색 (예: BD-케이스-500*350)
2 케이스용 연기차단재 null EST-SMOKE-케이스용 14912 고정 매핑
3 케이스 마구리 null BD-마구리-{규격} lookup 규격으로 items 검색 (예: BD-마구리-505*355)
4 가이드레일 null BD-가이드레일-{모델}-{재질}-{규격} lookup 모델+재질+규격으로 검색
5 레일용 연기차단재 null EST-SMOKE-레일용 14911 고정 매핑
6 하장바 null 00035 또는 00036 14158/14159 재질에 따라 분기
7 L바 null BD-L-BAR-{모델}-{규격} lookup 모델+규격으로 검색 (예: BD-L-BAR-KWE01-17*60)
8 보강평철 null BD-보강평철-50 14790 고정 매핑
9 무게평철12T null 00021 14147 고정 매핑 (평철12T와 동일)
10 환봉 null 90201~90204 14407~14410 파이 규격에 따라 분기 (30/35/45/50파이)

2.2 calculatePartItems (부자재) - 5종

# BOM 아이템명 현재 item_code SAM 매핑 코드 SAM item_id 매핑 방법
11 감기샤프트 null EST-SHAFT-{인치}-{길이} lookup 인치+길이로 검색 (예: EST-SHAFT-4-6)
12 각파이프 null EST-PIPE-{두께}-{길이} lookup 두께+길이로 검색 (예: EST-PIPE-1.4-6000)
13 모터받침 앵글 null EST-ANGLE-BRACKET-{타입} lookup 타입으로 검색 (스크린용/철제300K/400K/800K)
14 앵글 null EST-ANGLE-MAIN-{타입} lookup 앵글타입+길이로 검색
15 조인트바 null 800361 14733 고정 매핑

2.3 calculateDynamicItems (동적항목) - 7종

# BOM 아이템명 현재 item_code SAM 매핑 코드 SAM item_id 매핑 방법
16 검사비 KD-INSPECTION EST-INSPECTION (신규등록) items master 신규 등록 필요
17 주자재(스크린) KD-SCREEN EST-RAW-스크린-{타입} lookup 타입으로 검색 (실리카/화이바/와이어)
18 주자재(슬랫) KD-SLAT EST-RAW-슬랫-{타입} lookup 타입으로 검색 (방범/방화)
19 모터 KD-MOTOR-{용량} EST-MOTOR-{전압}-{용량} lookup 전압+용량으로 검색
20 제어기 KD-CTRL-{타입} EST-CTRL-{타입} lookup 타입으로 검색 (노출형/매립형)
21 뒷박스 KD-CTRL-BACKBOX EST-CTRL-뒷박스 14863 고정 매핑
22 브라켓 (모터에 포함) KD브라켓트* 또는 EST-* lookup 모터 용량에 따라 분기

굵은 글씨: 현재 미매핑 상태 (작업 대상)


3. 대상 범위

3.1 Phase 1: 미등록 아이템 등록 (사용자 승인 필요)

# 작업 항목 상태 비고
1.1 검사비(EST-INSPECTION) items master 신규 등록 ID: 14913
1.2 무게평철12T → 00021(평철12T) 동일 아이템 확인 ID: 14147 확인 완료

3.2 Phase 2: BOM 산출 로직 매핑 수정

# 작업 항목 상태 비고
2.1 calculateSteelItems: 10종 아이템에 item_code/item_id 매핑 withItemMapping 헬퍼 사용
2.2 calculatePartItems: 5종 아이템에 item_code/item_id 매핑 withItemMapping 헬퍼 사용
2.3 calculateDynamicItems: KD-* → EST-* 코드 변환 모터/제어기/주자재 매핑 완료

3.3 Phase 3: 검증

# 작업 항목 상태 비고
3.1 견적 산출 실행 → 모든 아이템 item_code/item_id 확인 18종 아이템 모두 매핑됨
3.2 수주 등록 → 코드 기반 아이템 그룹핑/집계 정상 동작 화면 검증 필요

4. 실행 환경 및 명령어

4.1 Docker 환경

# API 컨테이너 접속
docker exec -it sam-api-1 bash

# PHP Tinker 실행
docker exec sam-api-1 php artisan tinker --execute='...'

4.2 주요 확인 명령어

# SAM items master에서 특정 코드 검색
docker exec sam-api-1 php artisan tinker --execute='
$item = \App\Models\Items\Item::where("tenant_id", 287)
    ->where("code", "EST-INSPECTION")
    ->first();
echo $item ? "ID: {$item->id}, Code: {$item->code}, Name: {$item->name}" : "NOT FOUND";
'

# 코드 패턴으로 검색 (BD-*, EST-* 등)
docker exec sam-api-1 php artisan tinker --execute='
$items = \App\Models\Items\Item::where("tenant_id", 287)
    ->where("code", "like", "BD-마구리%")
    ->get(["id", "code", "name"]);
foreach ($items as $item) {
    echo "{$item->id} | {$item->code} | {$item->name}" . PHP_EOL;
}
'

# 5130 chandj DB 연결 테스트
docker exec sam-api-1 php artisan tinker --execute='
$count = \Illuminate\Support\Facades\DB::connection("chandj")
    ->table("KDunitprice")->count();
echo "KDunitprice 총 건수: {$count}";
'

4.3 검사비 신규 등록 (Phase 1.1)

# 검사비 아이템 신규 등록
docker exec sam-api-1 php artisan tinker --execute='
$item = \App\Models\Items\Item::create([
    "tenant_id" => 287,
    "code" => "EST-INSPECTION",
    "name" => "검사비",
    "unit" => "EA",
    "item_type" => "product",
    "is_active" => true,
]);
echo "Created: ID={$item->id}, Code={$item->code}";
'

5. 코드 수정 가이드

5.1 수정 대상 파일

api/app/Services/Quote/FormulaHandlers/KyungdongFormulaHandler.php

5.2 수정 패턴 (예시: calculateSteelItems 내 케이스 마구리)

현재 코드 (item_code 없음):

$items[] = [
    'item_name' => '케이스 마구리',
    'item_code' => null,  // ❌ 없음
    'item_id' => null,    // ❌ 없음
    'quantity' => $quantity,
    'unit_price' => $unitPrice,
    'total_price' => $quantity * $unitPrice,
    // ...
];

수정 후 (item_code/item_id 매핑):

// 규격 계산 (예: 505*355)
$spec = "{$caseWidth}*{$caseDepth}";
$itemCode = "BD-마구리-{$spec}";

// items master에서 lookup
$item = \App\Models\Items\Item::where('tenant_id', $this->tenantId)
    ->where('code', $itemCode)
    ->first();

$items[] = [
    'item_name' => '케이스 마구리',
    'item_code' => $item?->code ?? $itemCode,  // ✅ 코드 매핑
    'item_id' => $item?->id,                    // ✅ ID 매핑
    'quantity' => $quantity,
    'unit_price' => $unitPrice,
    'total_price' => $quantity * $unitPrice,
    // ...
];

5.3 아이템 lookup 헬퍼 메서드 추가 (권장)

/**
 * items master에서 코드로 아이템 조회
 */
private function lookupItem(string $code): ?Item
{
    return Item::where('tenant_id', $this->tenantId)
        ->where('code', $code)
        ->first();
}

/**
 * 아이템 배열에 item_code/item_id 추가
 */
private function withItemMapping(array $item, string $code): array
{
    $masterItem = $this->lookupItem($code);
    return array_merge($item, [
        'item_code' => $masterItem?->code ?? $code,
        'item_id' => $masterItem?->id,
    ]);
}

6. 검증 방법

6.1 견적 산출 후 BOM 결과 확인

# 최근 견적의 BOM 결과에서 item_code 확인
docker exec sam-api-1 php artisan tinker --execute='
$quote = \App\Models\Quote::where("tenant_id", 287)
    ->whereNotNull("calculation_result")
    ->latest()
    ->first();

$items = $quote->calculation_result["items"] ?? [];
$noCode = array_filter($items, fn($i) => empty($i["item_code"]));

echo "총 아이템: " . count($items) . "개" . PHP_EOL;
echo "item_code 없음: " . count($noCode) . "개" . PHP_EOL;

foreach ($noCode as $i) {
    echo "  - {$i["item_name"]}" . PHP_EOL;
}
'

6.2 수주 등록 화면 확인

  1. /orders/create?quoteId={ID}로 수주 등록 화면 진입
  2. 아이템 목록에서 동일 아이템이 코드 기준으로 집계되는지 확인
  3. 3개소에 "환봉" 각 1개 → "환봉" 1행, 수량 3개로 표시되어야 함

7. 성공 기준

기준 검증 방법 달성
BOM 산출 22종 아이템 전부 item_code 보유 Phase 3.1 검증 쿼리
BOM 산출 22종 아이템 전부 item_id 보유 Phase 3.1 검증 쿼리
수주 등록 시 코드 기반 아이템 집계 정상 동작 Phase 3.2 화면 확인
기존 견적 산출 금액에 영향 없음 기존 견적 재산출 후 금액 비교

8. 관련 소스 파일

파일 수정 여부 용도
api/app/Services/Quote/FormulaHandlers/KyungdongFormulaHandler.php 수정 BOM 산출 매핑 로직 추가
api/app/Models/Items/Item.php 읽기 items lookup
react/src/components/orders/OrderRegistration.tsx 검증 수주 등록 아이템 그룹핑
react/src/components/orders/actions.ts 검증 수주 데이터 변환

9. 참고 정보

9.1 SAM 견적 전용 코드 체계

접두사 용도 예시
BD- 절곡품 (모델/규격별) BD-케이스-500350, BD-마구리-505355
EST- 견적 산출 전용 EST-MOTOR-220V-300K, EST-INSPECTION
PT- 품목 템플릿 (규격 미포함) PT-케이스, PT-가이드레일
PM- 제어기 부품 PM-020 (제어기 노출형)

9.2 5130 DB 연결 정보

# api/.env
CHANDJ_DB_HOST=sam-mysql-1
CHANDJ_DB_DATABASE=chandj
CHANDJ_DB_USERNAME=root
CHANDJ_DB_PASSWORD=root

9.3 상세 분석 문서

  • 전체 분석 결과: docs/data/analysis/bom-item-mapping-analysis.md
  • 견적 시스템 구조: docs/features/quotes/README.md

10. 컨펌 대기 목록

# 항목 변경 내용 승인
1 검사비 신규 등록 items master에 EST-INSPECTION 추가
2 무게평철12T 동일성 BOM의 무게평철12T = 00021 평철12T 인지

11. 변경 이력

날짜 작업 변경 내용 파일
2026-02-05 분석 22종 아이템 매핑 상태 분석 완료 bom-item-mapping-analysis.md
2026-02-05 계획 작업 계획 문서 작성 bom-item-mapping-plan.md
2026-02-05 Phase 1 검사비(EST-INSPECTION) ID:14913 신규 등록 items master
2026-02-05 Phase 2 KyungdongFormulaHandler 매핑 로직 추가 KyungdongFormulaHandler.php

이 문서는 /sc:plan 스킬로 생성되었습니다.